Skip to content

Commit 9b66bc3

Browse files
committed
[PEM] add samples
1 parent 404a56e commit 9b66bc3

File tree

3 files changed

+299
-0
lines changed

3 files changed

+299
-0
lines changed

build-logic/src/main/kotlin/ckbuild.documentation.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,17 @@ dokka {
2525
localDirectory = rootDir
2626
remoteUrl("https://github.com/whyoleg/cryptography-kotlin/tree/$version/")
2727
}
28+
29+
if (name.endsWith("Main")) {
30+
samples.from("src/${name.replace("Main", "Samples")}/kotlin")
31+
}
32+
}
33+
}
34+
35+
kotlin {
36+
sourceSets.configureEach {
37+
if (name.endsWith("Test")) {
38+
kotlin.srcDir("src/${name.replace("Test", "Samples")}/kotlin")
39+
}
2840
}
2941
}

cryptography-serialization/pem/src/commonMain/kotlin/PemDocument.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public class PemDocument(
6060
* ```
6161
*
6262
* @return the PEM-encoded string
63+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.encodeToString
6364
*/
6465
public fun encodeToString(): String = encodeToByteArrayImpl().decodeToString()
6566

@@ -75,6 +76,7 @@ public class PemDocument(
7576
* ```
7677
*
7778
* @return the bytes representing PEM-encoded string
79+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.encodeToByteArray
7880
*/
7981
public fun encodeToByteArray(): ByteArray = encodeToByteArrayImpl()
8082

@@ -90,6 +92,7 @@ public class PemDocument(
9092
* ```
9193
*
9294
* @return the bytes representing PEM-encoded string
95+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.encodeToByteString
9396
*/
9497
@OptIn(UnsafeByteStringApi::class)
9598
public fun encodeToByteString(): ByteString = UnsafeByteStringOperations.wrapUnsafe(encodeToByteArrayImpl())
@@ -106,6 +109,7 @@ public class PemDocument(
106109
* ```
107110
*
108111
* @param sink the destination to write bytes representing PEM-encoded string into
112+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.encodeToSink
109113
*/
110114
public fun encodeToSink(sink: Sink): Unit = sink.write(encodeToByteArrayImpl())
111115

@@ -161,6 +165,7 @@ public class PemDocument(
161165
* @param text the textual input that may contain a PEM document
162166
* @return the decoded [PemDocument]
163167
* @throws IllegalArgumentException if no PEM documents present in [text], or the PEM encoding is invalid
168+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeFromString
164169
*/
165170
public fun decode(text: String): PemDocument {
166171
return tryDecodeFromString(text, startIndex = 0, saveEndIndex = {}) ?: throwPemMissingBeginLabel()
@@ -188,6 +193,7 @@ public class PemDocument(
188193
* @param text the textual input that may contain multiple PEM documents
189194
* @return a sequence of decoded [PemDocument]s, empty sequence if no PEM documents present
190195
* @throws IllegalArgumentException if the PEM encoding of any document is invalid
196+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeToSequenceFromString
191197
*/
192198
public fun decodeToSequence(text: String): Sequence<PemDocument> = sequence {
193199
var startIndex = 0
@@ -215,6 +221,7 @@ public class PemDocument(
215221
* @param bytes the byte array that may contain a PEM document
216222
* @return the decoded [PemDocument]
217223
* @throws IllegalArgumentException if no PEM documents present in [bytes], or the PEM encoding is invalid
224+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeFromByteArray
218225
*/
219226
@OptIn(UnsafeByteStringApi::class)
220227
public fun decode(bytes: ByteArray): PemDocument {
@@ -244,6 +251,7 @@ public class PemDocument(
244251
* @param bytes the byte array that may contain multiple PEM documents
245252
* @return a sequence of decoded [PemDocument]s, empty sequence if no PEM documents present
246253
* @throws IllegalArgumentException if the PEM encoding of any document is invalid
254+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeToSequenceFromByteArray
247255
*/
248256
@OptIn(UnsafeByteStringApi::class)
249257
public fun decodeToSequence(bytes: ByteArray): Sequence<PemDocument> {
@@ -269,6 +277,7 @@ public class PemDocument(
269277
* @param bytes the byte array that may contain a PEM document
270278
* @return the decoded [PemDocument]
271279
* @throws IllegalArgumentException if no PEM documents present in [bytes], or the PEM encoding is invalid
280+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeFromByteString
272281
*/
273282
public fun decode(bytes: ByteString): PemDocument {
274283
return tryDecodeFromByteString(bytes, startIndex = 0, saveEndIndex = {}) ?: throwPemMissingBeginLabel()
@@ -297,6 +306,7 @@ public class PemDocument(
297306
* @param bytes the byte array that may contain multiple PEM documents
298307
* @return a sequence of decoded [PemDocument]s, empty sequence if no PEM documents present
299308
* @throws IllegalArgumentException if the PEM encoding of any document is invalid
309+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeToSequenceFromByteString
300310
*/
301311
public fun decodeToSequence(bytes: ByteString): Sequence<PemDocument> = sequence {
302312
var startIndex = 0
@@ -325,6 +335,7 @@ public class PemDocument(
325335
* @param source the source to read from
326336
* @return the decoded [PemDocument]
327337
* @throws IllegalArgumentException if no PEM documents present in [source], or the PEM encoding is invalid
338+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeFromSource
328339
*/
329340
public fun decode(source: Source): PemDocument {
330341
return tryDecodeFromSource(source) ?: throwPemMissingBeginLabel()
@@ -353,6 +364,7 @@ public class PemDocument(
353364
* @param source the source to read from
354365
* @return a sequence of decoded [PemDocument]s, empty sequence if no PEM documents present
355366
* @throws IllegalArgumentException if the PEM encoding of any document is invalid
367+
* @sample dev.whyoleg.cryptography.serialization.pem.PemSamples.decodeToSequenceFromSource
356368
*/
357369
public fun decodeToSequence(source: Source): Sequence<PemDocument> = sequence {
358370
while (!source.exhausted()) {
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
/*
2+
* Copyright (c) 2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.whyoleg.cryptography.serialization.pem
6+
7+
import kotlinx.io.*
8+
import kotlinx.io.bytestring.*
9+
import kotlin.test.*
10+
11+
class PemSamples {
12+
@Test
13+
fun encodeToString() {
14+
val document = PemDocument(
15+
label = PemLabel("CUSTOM"),
16+
content = "hello world".encodeToByteString(),
17+
)
18+
19+
val encoded = document.encodeToString()
20+
21+
assertEquals(
22+
expected = """
23+
-----BEGIN CUSTOM-----
24+
aGVsbG8gd29ybGQ=
25+
-----END CUSTOM-----
26+
27+
""".trimIndent(),
28+
actual = encoded
29+
)
30+
}
31+
32+
@Test
33+
fun encodeToByteArray() {
34+
val document = PemDocument(
35+
label = PemLabel("CUSTOM"),
36+
content = "hello world".encodeToByteString(),
37+
)
38+
39+
val encoded = document.encodeToByteArray()
40+
41+
assertContentEquals(
42+
expected = """
43+
-----BEGIN CUSTOM-----
44+
aGVsbG8gd29ybGQ=
45+
-----END CUSTOM-----
46+
47+
""".trimIndent().encodeToByteArray(),
48+
actual = encoded
49+
)
50+
}
51+
52+
@Test
53+
fun encodeToByteString() {
54+
val document = PemDocument(
55+
label = PemLabel("CUSTOM"),
56+
content = "hello world".encodeToByteString(),
57+
)
58+
59+
val encoded = document.encodeToByteString()
60+
61+
assertEquals(
62+
expected = """
63+
-----BEGIN CUSTOM-----
64+
aGVsbG8gd29ybGQ=
65+
-----END CUSTOM-----
66+
67+
""".trimIndent().encodeToByteString(),
68+
actual = encoded
69+
)
70+
}
71+
72+
@Test
73+
fun encodeToSink() {
74+
val document = PemDocument(
75+
label = PemLabel("CUSTOM"),
76+
content = "hello world".encodeToByteString(),
77+
)
78+
79+
val buffer = Buffer()
80+
document.encodeToSink(buffer)
81+
val encoded = buffer.readString()
82+
83+
assertEquals(
84+
expected = """
85+
-----BEGIN CUSTOM-----
86+
aGVsbG8gd29ybGQ=
87+
-----END CUSTOM-----
88+
89+
""".trimIndent(),
90+
actual = encoded
91+
)
92+
}
93+
94+
@Test
95+
fun decodeFromString() {
96+
val pem: String = """
97+
-----BEGIN CUSTOM-----
98+
aGVsbG8gd29ybGQ=
99+
-----END CUSTOM-----
100+
101+
""".trimIndent()
102+
103+
val document = PemDocument.decode(pem)
104+
105+
assertEquals(
106+
expected = PemDocument(
107+
label = PemLabel("CUSTOM"),
108+
content = "hello world".encodeToByteString()
109+
),
110+
actual = document
111+
)
112+
}
113+
114+
@Test
115+
fun decodeFromByteArray() {
116+
val pem: ByteArray = """
117+
-----BEGIN CUSTOM-----
118+
aGVsbG8gd29ybGQ=
119+
-----END CUSTOM-----
120+
121+
""".trimIndent().encodeToByteArray()
122+
123+
val document = PemDocument.decode(pem)
124+
125+
assertEquals(
126+
expected = PemDocument(
127+
label = PemLabel("CUSTOM"),
128+
content = "hello world".encodeToByteString()
129+
),
130+
actual = document
131+
)
132+
}
133+
134+
@Test
135+
fun decodeFromByteString() {
136+
val pem: ByteString = """
137+
-----BEGIN CUSTOM-----
138+
aGVsbG8gd29ybGQ=
139+
-----END CUSTOM-----
140+
141+
""".trimIndent().encodeToByteString()
142+
143+
val document = PemDocument.decode(pem)
144+
145+
assertEquals(
146+
expected = PemDocument(
147+
label = PemLabel("CUSTOM"),
148+
content = "hello world".encodeToByteString()
149+
),
150+
actual = document
151+
)
152+
}
153+
154+
@Test
155+
fun decodeFromSource() {
156+
val pem = """
157+
-----BEGIN CUSTOM-----
158+
aGVsbG8gd29ybGQ=
159+
-----END CUSTOM-----
160+
161+
""".trimIndent()
162+
163+
val buffer = Buffer()
164+
buffer.writeString(pem)
165+
166+
val document = PemDocument.decode(buffer)
167+
168+
assertEquals(
169+
expected = PemDocument(
170+
label = PemLabel("CUSTOM"),
171+
content = "hello world".encodeToByteString()
172+
),
173+
actual = document
174+
)
175+
}
176+
177+
@Test
178+
fun decodeToSequenceFromString() {
179+
val pem: String = """
180+
-----BEGIN A-----
181+
YQ==
182+
-----END A-----
183+
184+
-----BEGIN B-----
185+
Yg==
186+
-----END B-----
187+
188+
""".trimIndent()
189+
190+
val documents = PemDocument.decodeToSequence(pem).toList()
191+
192+
assertEquals(
193+
expected = listOf(
194+
PemDocument(PemLabel("A"), "a".encodeToByteString()),
195+
PemDocument(PemLabel("B"), "b".encodeToByteString()),
196+
),
197+
actual = documents,
198+
)
199+
}
200+
201+
@Test
202+
fun decodeToSequenceFromByteArray() {
203+
val pem: ByteArray = """
204+
-----BEGIN A-----
205+
YQ==
206+
-----END A-----
207+
208+
-----BEGIN B-----
209+
Yg==
210+
-----END B-----
211+
212+
""".trimIndent().encodeToByteArray()
213+
214+
val documents = PemDocument.decodeToSequence(pem).toList()
215+
216+
assertEquals(
217+
expected = listOf(
218+
PemDocument(PemLabel("A"), "a".encodeToByteString()),
219+
PemDocument(PemLabel("B"), "b".encodeToByteString()),
220+
),
221+
actual = documents,
222+
)
223+
}
224+
225+
@Test
226+
fun decodeToSequenceFromByteString() {
227+
val pem: ByteString = """
228+
-----BEGIN A-----
229+
YQ==
230+
-----END A-----
231+
232+
-----BEGIN B-----
233+
Yg==
234+
-----END B-----
235+
236+
""".trimIndent().encodeToByteString()
237+
238+
val documents = PemDocument.decodeToSequence(pem).toList()
239+
240+
assertEquals(
241+
expected = listOf(
242+
PemDocument(PemLabel("A"), "a".encodeToByteString()),
243+
PemDocument(PemLabel("B"), "b".encodeToByteString()),
244+
),
245+
actual = documents,
246+
)
247+
}
248+
249+
@Test
250+
fun decodeToSequenceFromSource() {
251+
val pem = """
252+
-----BEGIN A-----
253+
YQ==
254+
-----END A-----
255+
256+
-----BEGIN B-----
257+
Yg==
258+
-----END B-----
259+
260+
""".trimIndent()
261+
262+
val buffer = Buffer()
263+
buffer.writeString(pem)
264+
265+
val documents = PemDocument.decodeToSequence(buffer).toList()
266+
267+
assertEquals(
268+
expected = listOf(
269+
PemDocument(PemLabel("A"), "a".encodeToByteString()),
270+
PemDocument(PemLabel("B"), "b".encodeToByteString()),
271+
),
272+
actual = documents,
273+
)
274+
}
275+
}

0 commit comments

Comments
 (0)