Skip to content

Commit

Permalink
Add 'names.ToCamelCase'.
Browse files Browse the repository at this point in the history
  • Loading branch information
ewbankkit committed Jan 27, 2025
1 parent 9208941 commit a77b40e
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 0 deletions.
63 changes: 63 additions & 0 deletions names/camel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package names

import (
"strings"
)

// toCamelCase converts a string to CamelCase.
func toCamelCase(in string, initialCap bool) string {
out := strings.Builder{}

nextIsCap := initialCap
prevIsCap := false
for i, ch := range []byte(in) {
isCap := isCapitalLetter(ch)
isLow := isLowercaseLetter(ch)
isDig := isNumeric(ch)

if nextIsCap {
if isLow {
ch = toUppercaseLetter(ch)
}
} else if i == 0 {
if isCap {
ch = toLowercaseLetter(ch)
}
} else if prevIsCap && isCap {
ch = toLowercaseLetter(ch)
}

prevIsCap = isCap

if isCap || isLow {
out.WriteByte(ch)
nextIsCap = false
} else if isDig {
out.WriteByte(ch)
nextIsCap = true
} else {
nextIsCap = ch == '_' || ch == ' ' || ch == '-' || ch == '.'
}
}

return out.String()
}

func toUppercaseLetter(ch byte) byte {
ch += 'A'
ch -= 'a'
return ch
}

// ToCamelCase converts a string to CamelCase.
func ToCamelCase(in string) string {
return toCamelCase(in, true)
}

// ToLowerCamelCase converts a string to camelCase.
func ToLowerCamelCase(in string) string {
return toCamelCase(in, false)
}
125 changes: 125 additions & 0 deletions names/camel_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package names

import (
"testing"
)

func TestToCamelCase(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
input string
expected string
}{
{
name: "empty",
input: "",
expected: "",
},
{
name: "All lower",
input: "lower",
expected: "Lower",
},
{
name: "Initial upper",
input: "Lower",
expected: "Lower",
},
{
name: "Two words",
input: "Two words",
expected: "TwoWords",
},
{
name: "Three words",
input: "TheseThreeWords",
expected: "TheseThreeWords",
},
{
name: "A long one",
input: "global-Replication_Group.description",
expected: "GlobalReplicationGroupDescription",
},
{
name: "Including a digit",
input: "s3bucket",
expected: "S3Bucket",
},
{
name: "Constant case",
input: "CONSTANT_CASE",
expected: "ConstantCase",
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

if got, want := ToCamelCase(testCase.input), testCase.expected; got != want {
t.Errorf("got: %s, expected: %s", got, want)
}
})
}
}

func TestToLowerCamelCase(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
input string
expected string
}{
{
name: "empty",
input: "",
expected: "",
},
{
name: "All lower",
input: "lower",
expected: "lower",
},
{
name: "Initial upper",
input: "Lower",
expected: "lower",
},
{
name: "Two words",
input: "Two words",
expected: "twoWords",
},
{
name: "Three words",
input: "TheseThreeWords",
expected: "theseThreeWords",
},
{
name: "A long one",
input: "global-Replication_Group.description",
expected: "globalReplicationGroupDescription",
},
{
name: "Including a digit",
input: "s3bucket",
expected: "s3Bucket",
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

if got, want := ToLowerCamelCase(testCase.input), testCase.expected; got != want {
t.Errorf("got: %s, expected: %s", got, want)
}
})
}
}
5 changes: 5 additions & 0 deletions names/snake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ func TestToSnakeCase(t *testing.T) {
input: "ResourceARN",
expected: "resource_arn",
},
{
name: "Resource-ARN",
input: "Resource-ARN",
expected: "resource_arn",
},
}

for _, testCase := range testCases {
Expand Down

0 comments on commit a77b40e

Please sign in to comment.