Skip to content

Commit c9fd7d0

Browse files
committed
GH-185 Support colon in keys & release 1.14.7 (Fix #185)
1 parent 01ccf5d commit c9fd7d0

File tree

10 files changed

+111
-21
lines changed

10 files changed

+111
-21
lines changed

.github/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ repositories {
3434
3535
dependencies {
3636
// Default
37-
implementation 'net.dzikoysk:cdn:1.14.6'
37+
implementation 'net.dzikoysk:cdn:1.14.7'
3838
// Kotlin wrapper
39-
implementation 'net.dzikoysk:cdn-kt:1.14.6'
39+
implementation 'net.dzikoysk:cdn-kt:1.14.7'
4040
}
4141
```
4242

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ allprojects {
1717
apply(plugin = "maven-publish")
1818

1919
group = "net.dzikoysk"
20-
version = "1.14.6"
20+
version = "1.14.7"
2121

2222
repositories {
2323
maven("https://maven.reposilite.com/maven-central")

cdn-tests/src/test/kotlin/net/dzikoysk/cdn/CdnReaderTest.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,42 @@ class CdnReaderTest : CdnSpec() {
8282
assertEquals(" value ", result.getString(" key ", "value"))
8383
}
8484

85+
@Test
86+
fun `should read quoted key and value with tricky values`() {
87+
val result = assertOk(standard.load(Source.of("""
88+
"key:": " value "
89+
""")))
90+
91+
assertEquals(" value ", result.getString("key:").get())
92+
}
93+
94+
@Test
95+
fun `GH-185 should read weird keys`() {
96+
val result = assertOk(standard.load(Source.of("""
97+
':lenny:': ( ͡° ͜ʖ ͡°)
98+
':tableflip:': (╯°□°)╯︵ ┻━┻
99+
'<3': ❤
100+
':swag:': (⌐■_■)
101+
':yes:': ✔
102+
':dog:': 7V●ᴥ●V
103+
':shrug:': ¯\_(ツ)_/¯
104+
':angry:': (ノಠ益ಠ)ノ
105+
':no:': ❌
106+
'o/': ( ゚◡゚)/
107+
""")))
108+
109+
assertEquals("( ͡° ͜ʖ ͡°)", result.getString(":lenny:").get())
110+
assertEquals("(╯°□°)╯︵ ┻━┻", result.getString(":tableflip:").get())
111+
assertEquals("", result.getString("<3").get())
112+
assertEquals("(⌐■_■)", result.getString(":swag:").get())
113+
assertEquals("", result.getString(":yes:").get())
114+
assertEquals("7V●ᴥ●V", result.getString(":dog:").get())
115+
assertEquals("¯\\_(ツ)_/¯", result.getString(":shrug:").get())
116+
assertEquals("(ノಠ益ಠ)ノ", result.getString(":angry:").get())
117+
assertEquals("", result.getString(":no:").get())
118+
assertEquals("( ゚◡゚)/", result.getString("o/").get())
119+
}
120+
85121
@Test
86122
fun `should remove semicolons`() {
87123
val result = assertOk(standard.load(Source.of("""

cdn-tests/src/test/kotlin/net/dzikoysk/cdn/module/standard/StandardSerializerTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class StandardSerializerTest : CdnSpec() {
3737
# List description
3838
list [
3939
record
40-
record : with : semicolons
40+
"record : with : semicolons"
4141
]
4242
# Custom object
4343
custom {

cdn-tests/src/test/kotlin/net/dzikoysk/cdn/serdes/composers/ListComposerTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ class ListComposerTest : CdnSpec() {
4848

4949
val expectedSource = cfg("""
5050
list [
51-
a:1
52-
b:2
51+
"a:1"
52+
"b:2"
5353
]
5454
""")
5555

cdn-tests/src/test/kotlin/net/dzikoysk/cdn/serdes/composers/SimpleComposerTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class SimpleComposerTest : CdnSpec() {
3030
var separator = ", "
3131
var singleQuote = "\""
3232
var quotes = "\"\""
33+
var singleQuotes = "'"
34+
var backticks = "`"
3335
var empty = ""
3436
}
3537

cdn/src/main/java/net/dzikoysk/cdn/CdnUtils.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ public static boolean isKotlinDataClass(Class<?> clazz) {
212212

213213
private static final List<Predicate<String>> LITERAL_FILTERS = asList(
214214
(value) -> ObjectUtils.equalsOneOf(value, "true", "false"),
215-
(value) -> Result.attempt(() -> Double.parseDouble(value)).isOk()
215+
(value) -> Result.supplyThrowing(() -> Double.parseDouble(value)).isOk()
216216
);
217217

218218
public static String destringify(String raw) {
@@ -232,25 +232,30 @@ public static String destringify(String raw) {
232232
}
233233

234234
public static boolean isStringified(String value) {
235-
return value.startsWith("\"") && value.endsWith("\"");
235+
for (String operator : StandardOperators.STRING_OPERATORS) {
236+
if (value.startsWith(operator) && value.endsWith(operator)) {
237+
return true;
238+
}
239+
}
240+
return false;
241+
}
242+
243+
public static String stringify(boolean enforce, String value) {
244+
return enforce ? forceStringify(value) : value;
236245
}
237246

238247
public static String stringify(String value) {
239248
String raw = value.replace(StandardOperators.LINE_SEPARATOR, StandardOperators.RAW_LINE_SEPARATOR);
240249

241250
if (!isStringified(raw)) {
242-
if (raw.isEmpty() || raw.trim().length() != raw.length() || raw.endsWith(",") || raw.endsWith("{") || raw.endsWith(":")) {
243-
return "\"" + raw + "\"";
251+
if (raw.isEmpty() || raw.trim().length() != raw.length() || raw.contains(",") || raw.contains("{") || raw.contains(":")) {
252+
return stringifyValue(raw);
244253
}
245254
}
246255

247256
return raw;
248257
}
249258

250-
public static String stringify(boolean enforce, String value) {
251-
return enforce ? forceStringify(value) : value;
252-
}
253-
254259
public static String forceStringify(String value) {
255260
for (Predicate<String> literalFilter : LITERAL_FILTERS) {
256261
if (literalFilter.test(value)) {
@@ -259,12 +264,25 @@ public static String forceStringify(String value) {
259264
}
260265

261266
if (!isStringified(value)) {
262-
return "\"" + value + "\"";
267+
return stringifyValue(value);
263268
}
264269

265270
return value;
266271
}
267272

273+
private static String stringifyValue(String raw) {
274+
if (raw.contains("\"")) {
275+
if (raw.contains("'")) {
276+
if (raw.contains("`")) {
277+
throw new IllegalArgumentException("Cannot stringify value: " + raw);
278+
}
279+
return "`" + raw + "`";
280+
}
281+
return "'" + raw + "'";
282+
}
283+
return "\"" + raw + "\"";
284+
}
285+
268286
public static <K, V, E extends Exception> Map<K, V> streamOfResultPairToMap(PandaStream<Result<Pair<K, V>, E>> stream) {
269287
return stream
270288
.filter(Result::isOk)

cdn/src/main/java/net/dzikoysk/cdn/model/Entry.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package net.dzikoysk.cdn.model;
1818

19-
import net.dzikoysk.cdn.CdnUtils;
2019
import net.dzikoysk.cdn.module.standard.StandardOperators;
2120

2221
import java.util.List;

cdn/src/main/java/net/dzikoysk/cdn/model/Piece.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,46 @@
1818

1919
import net.dzikoysk.cdn.module.standard.StandardOperators;
2020
import panda.utilities.StringUtils;
21-
import java.util.Collections;
22-
import java.util.List;
21+
22+
import java.util.*;
2323

2424
/**
2525
* Represents the smallest piece of information in configuration
2626
*/
2727
public final class Piece implements Element<String> {
2828

29+
private static final Set<String> STRING_OPERATORS = new HashSet<>(Arrays.asList(StandardOperators.STRING_OPERATORS));
30+
2931
private final String value;
3032

3133
public Piece(String value) {
32-
this.value = value;
34+
this.value = value.trim();
3335
}
3436

3537
public Entry toEntry(List<? extends String> description) {
36-
String[] elements = StringUtils.splitFirst(value, StandardOperators.OPERATOR);
38+
String openingSymbol = Character.toString(value.charAt(0));
39+
String[] elements;
40+
41+
if (isStringOperator(openingSymbol)) {
42+
StringBuilder entryKey = new StringBuilder(openingSymbol);
43+
int readIndex = 1;
44+
45+
for (; readIndex < value.length(); readIndex++) {
46+
String currentChar = Character.toString(value.charAt(readIndex));
47+
entryKey.append(currentChar);
48+
49+
if (currentChar.equals(openingSymbol)) {
50+
break;
51+
}
52+
}
53+
54+
elements = new String[] {
55+
entryKey.toString(),
56+
StringUtils.split(value.substring(readIndex + 1), StandardOperators.OPERATOR)[1].trim()
57+
};
58+
} else {
59+
elements = StringUtils.splitFirst(value, StandardOperators.OPERATOR);
60+
}
3761

3862
String entryKey = elements.length > 0
3963
? elements[0].trim()
@@ -50,6 +74,15 @@ public Entry toEntry(List<? extends String> description) {
5074
return new Entry(description, value, entryKey, entryValue);
5175
}
5276

77+
private boolean isStringOperator(String operator) {
78+
for (String stringOperator : StandardOperators.STRING_OPERATORS) {
79+
if (stringOperator.equals(operator)) {
80+
return true;
81+
}
82+
}
83+
return false;
84+
}
85+
5386
@Override
5487
public String toString() {
5588
return "Unit { " + value + " }";

cdn/src/main/java/net/dzikoysk/cdn/model/Section.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,13 @@ public Option<Element<?>> get(String key) {
9898
return Option.none();
9999
}
100100

101+
String stringifiedKey = CdnUtils.stringify(key);
102+
101103
for (Element<?> element : getValue()) {
102104
if (element instanceof NamedElement) {
103105
NamedElement<?> namedElement = (NamedElement<?>) element;
104106

105-
if (key.equals(namedElement.getName())) {
107+
if (key.equals(CdnUtils.destringify(namedElement.getName()))) {
106108
return Option.of(element);
107109
}
108110
}

0 commit comments

Comments
 (0)