|  | """Starlark helpers for Objective-C protos.""" | 
|  |  | 
|  | # State constants for objc_proto_camel_case_name. | 
|  | _last_was_other = 0 | 
|  | _last_was_lowercase = 1 | 
|  | _last_was_uppercase = 2 | 
|  | _last_was_number = 3 | 
|  |  | 
|  | def objc_proto_camel_case_name(name): | 
|  | """A Starlark version of the ObjC generator's CamelCase name transform. | 
|  |  | 
|  | This needs to track | 
|  | src/google/protobuf/compiler/objectivec/names.cc's UnderscoresToCamelCase() | 
|  |  | 
|  | NOTE: This code is written to model the C++ in protoc's ObjC generator so it | 
|  | is easier to confirm that the algorithms between the implementations match. | 
|  | The customizations for starlark performance are: | 
|  | - The cascade within the loop is reordered and special cases "_" to | 
|  | optimize for google3 inputs. | 
|  | - The "last was" state is handled via integers instead of three booleans. | 
|  |  | 
|  | The `first_capitalized` argument in the C++ code is left off this code and | 
|  | it acts as if the value were `True`. | 
|  |  | 
|  | Args: | 
|  | name: The proto file name to convert to camel case. The extension should | 
|  | already be removed. | 
|  |  | 
|  | Returns: | 
|  | The converted proto name to camel case. | 
|  | """ | 
|  | segments = [] | 
|  | current = "" | 
|  | last_was = _last_was_other | 
|  | for c in name.elems(): | 
|  | if c.islower(): | 
|  | # lowercase letter can follow a lowercase or uppercase letter. | 
|  | if last_was != _last_was_lowercase and last_was != _last_was_uppercase: | 
|  | segments.append(current) | 
|  | current = c.upper() | 
|  | else: | 
|  | current += c | 
|  | last_was = _last_was_lowercase | 
|  | elif c == "_":  # more common than rest, special case it. | 
|  | last_was = _last_was_other | 
|  | elif c.isdigit(): | 
|  | if last_was != _last_was_number: | 
|  | segments.append(current) | 
|  | current = "" | 
|  | current += c | 
|  | last_was = _last_was_number | 
|  | elif c.isupper(): | 
|  | if last_was != _last_was_uppercase: | 
|  | segments.append(current) | 
|  | current = c | 
|  | else: | 
|  | current += c.lower() | 
|  | last_was = _last_was_uppercase | 
|  | else: | 
|  | last_was = _last_was_other | 
|  | segments.append(current) | 
|  | result = "" | 
|  | for x in segments: | 
|  | if x in ("Url", "Http", "Https"): | 
|  | result += x.upper() | 
|  | else: | 
|  | result += x | 
|  | return result |