blob: 5535868bd7eb81d4bf89db776779a09c8575f541 [file] [log] [blame]
Protobuf Team Bote2aa06e2023-02-10 14:11:22 -08001"""Starlark helpers for Objective-C protos."""
2
3# State constants for objc_proto_camel_case_name.
4_last_was_other = 0
5_last_was_lowercase = 1
6_last_was_uppercase = 2
7_last_was_number = 3
8
9def objc_proto_camel_case_name(name):
10 """A Starlark version of the ObjC generator's CamelCase name transform.
11
12 This needs to track
13 src/google/protobuf/compiler/objectivec/names.cc's UnderscoresToCamelCase()
14
15 NOTE: This code is written to model the C++ in protoc's ObjC generator so it
16 is easier to confirm that the algorithms between the implementations match.
17 The customizations for starlark performance are:
18 - The cascade within the loop is reordered and special cases "_" to
19 optimize for google3 inputs.
20 - The "last was" state is handled via integers instead of three booleans.
21
22 The `first_capitalized` argument in the C++ code is left off this code and
23 it acts as if the value were `True`.
24
25 Args:
26 name: The proto file name to convert to camel case. The extension should
27 already be removed.
28
29 Returns:
30 The converted proto name to camel case.
31 """
32 segments = []
33 current = ""
34 last_was = _last_was_other
35 for c in name.elems():
36 if c.islower():
37 # lowercase letter can follow a lowercase or uppercase letter.
38 if last_was != _last_was_lowercase and last_was != _last_was_uppercase:
39 segments.append(current)
40 current = c.upper()
41 else:
42 current += c
43 last_was = _last_was_lowercase
44 elif c == "_": # more common than rest, special case it.
45 last_was = _last_was_other
46 elif c.isdigit():
47 if last_was != _last_was_number:
48 segments.append(current)
49 current = ""
50 current += c
51 last_was = _last_was_number
52 elif c.isupper():
53 if last_was != _last_was_uppercase:
54 segments.append(current)
55 current = c
56 else:
57 current += c.lower()
58 last_was = _last_was_uppercase
59 else:
60 last_was = _last_was_other
61 segments.append(current)
62 result = ""
63 for x in segments:
64 if x in ("Url", "Http", "Https"):
65 result += x.upper()
66 else:
67 result += x
68 return result