fixed objClass initialization in ObjInt.Zero, added Buffer.toBitInput, minimal descrription of Lynon
This commit is contained in:
parent
eefecae7b4
commit
835333dfad
@ -121,7 +121,7 @@ which is used in `toString`) and hex encoding:
|
|||||||
## Members
|
## Members
|
||||||
|
|
||||||
| name | meaning | type |
|
| name | meaning | type |
|
||||||
|---------------------------|-----------------------------------|---------------|
|
|----------------------------|-----------------------------------------|---------------|
|
||||||
| `size` | size | Int |
|
| `size` | size | Int |
|
||||||
| `decodeUtf8` | decode to String using UTF8 rules | Any |
|
| `decodeUtf8` | decode to String using UTF8 rules | Any |
|
||||||
| `+` | buffer concatenation | Any |
|
| `+` | buffer concatenation | Any |
|
||||||
@ -129,7 +129,8 @@ which is used in `toString`) and hex encoding:
|
|||||||
| `hex` | encode to hex strign | String |
|
| `hex` | encode to hex strign | String |
|
||||||
| `Buffer.decodeHex(hexStr) | decode hex string | Buffer |
|
| `Buffer.decodeHex(hexStr) | decode hex string | Buffer |
|
||||||
| `base64` | encode to base64 (url flavor) (2) | String |
|
| `base64` | encode to base64 (url flavor) (2) | String |
|
||||||
| `Buffer.decodeBase64` | decode base64 to new Buffer (2) | Buffer |
|
| `Buffer.decodeBase64(str)` | decode base64 to new Buffer (2) | Buffer |
|
||||||
|
| `toBitInput()` | create bit input from a byte buffer (3) | |
|
||||||
|
|
||||||
(1)
|
(1)
|
||||||
: optimized implementation that override `Iterable` one
|
: optimized implementation that override `Iterable` one
|
||||||
@ -139,6 +140,9 @@ which is used in `toString`) and hex encoding:
|
|||||||
decoding supports both traditional and URL alphabets automatically, and ignores filling `=` characters. Base64URL is
|
decoding supports both traditional and URL alphabets automatically, and ignores filling `=` characters. Base64URL is
|
||||||
well known and mentioned in the internet, for example, [here](https://base64.guru/standards/base64url).
|
well known and mentioned in the internet, for example, [here](https://base64.guru/standards/base64url).
|
||||||
|
|
||||||
|
(3)
|
||||||
|
: `BitInput` is a bit buffer that is used, for example, in [Lynon.decode](serialization.md)
|
||||||
|
|
||||||
Also, it inherits methods from [Iterable] and [Array].
|
Also, it inherits methods from [Iterable] and [Array].
|
||||||
|
|
||||||
|
|
||||||
|
46
docs/serialization.md
Normal file
46
docs/serialization.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Lyng serialization
|
||||||
|
|
||||||
|
Lyng has builting binary bit-effective serialization format, called Lynon for LYng Object Notation. It is typed, binary, implements caching, automatic compression, variable-length ints, one-bit Booleans an many nice features.
|
||||||
|
|
||||||
|
It is as simple as:
|
||||||
|
|
||||||
|
import lyng.serialization
|
||||||
|
|
||||||
|
val text = "
|
||||||
|
We hold these truths to be self-evident, that all men are created equal,
|
||||||
|
that they are endowed by their Creator with certain unalienable Rights,
|
||||||
|
that among these are Life, Liberty and the pursuit of Happiness.
|
||||||
|
"
|
||||||
|
val encodedBits = Lynon.encode(text)
|
||||||
|
|
||||||
|
// decode bits source:
|
||||||
|
assertEquals( text, Lynon.decode(encodedBits) )
|
||||||
|
|
||||||
|
// compression was used automatically
|
||||||
|
assert( text.length > encodedBits.toBuffer().size )
|
||||||
|
>>> void
|
||||||
|
|
||||||
|
Any class you create is serializable by default; lynon serializes first constructor fields, then any `var` member fields:
|
||||||
|
|
||||||
|
import lyng.serialization
|
||||||
|
|
||||||
|
class Point(x,y)
|
||||||
|
|
||||||
|
val p = Lynon.decode( Lynon.encode( Point(5,6) ) )
|
||||||
|
|
||||||
|
assertEquals( 5, p.x )
|
||||||
|
assertEquals( 6, p.y )
|
||||||
|
>>> void
|
||||||
|
|
||||||
|
|
||||||
|
just as expected.
|
||||||
|
|
||||||
|
Important is to understand that normally `Lynon.decode` wants [BitBuffer], as `Lynon.encode` produces. If you have the regular [Buffer], be sure to convert it:
|
||||||
|
|
||||||
|
buffer.toBitInput()
|
||||||
|
|
||||||
|
this possibly creates extra zero bits at the end, as bit content could be shorter than byte-grained but for the Lynon format it does not make sense. Note that when you serialize [BitBuffer], exact number of bits is written. To convert bit buffer to bytes:
|
||||||
|
|
||||||
|
Lynon.encode("hello").toBuffer()
|
||||||
|
|
||||||
|
(topic is incomplete and under construction)
|
@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "0.8.12-SNAPSHOT"
|
version = "0.8.14-SNAPSHOT"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -85,13 +85,15 @@ open class Obj {
|
|||||||
name: String,
|
name: String,
|
||||||
args: Arguments = Arguments.EMPTY,
|
args: Arguments = Arguments.EMPTY,
|
||||||
onNotFoundResult: Obj?=null
|
onNotFoundResult: Obj?=null
|
||||||
): Obj =
|
): Obj {
|
||||||
objClass.getInstanceMemberOrNull(name)?.value?.invoke(
|
return objClass.getInstanceMemberOrNull(name)?.value?.invoke(
|
||||||
scope,
|
scope,
|
||||||
this,
|
this,
|
||||||
args)
|
args
|
||||||
|
)
|
||||||
?: onNotFoundResult
|
?: onNotFoundResult
|
||||||
?: scope.raiseSymbolNotFound(name)
|
?: scope.raiseSymbolNotFound(name)
|
||||||
|
}
|
||||||
|
|
||||||
open suspend fun getInstanceMethod(
|
open suspend fun getInstanceMethod(
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
|
@ -24,6 +24,7 @@ import net.sergeych.bintools.encodeToHex
|
|||||||
import net.sergeych.bintools.toDump
|
import net.sergeych.bintools.toDump
|
||||||
import net.sergeych.lyng.Scope
|
import net.sergeych.lyng.Scope
|
||||||
import net.sergeych.lyng.statement
|
import net.sergeych.lyng.statement
|
||||||
|
import net.sergeych.lynon.BitArray
|
||||||
import net.sergeych.lynon.LynonDecoder
|
import net.sergeych.lynon.LynonDecoder
|
||||||
import net.sergeych.lynon.LynonEncoder
|
import net.sergeych.lynon.LynonEncoder
|
||||||
import net.sergeych.lynon.LynonType
|
import net.sergeych.lynon.LynonType
|
||||||
@ -200,6 +201,9 @@ open class ObjBuffer(val byteArray: UByteArray) : Obj() {
|
|||||||
thisAs<ObjBuffer>().byteArray.toByteArray().toDump()
|
thisAs<ObjBuffer>().byteArray.toByteArray().toDump()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
addFn("toBitInput") {
|
||||||
|
ObjBitBuffer(BitArray(thisAs<ObjBuffer>().byteArray, 8))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -62,7 +62,7 @@ class ObjInt(var value: Long, override val isConst: Boolean = false) : Obj(), Nu
|
|||||||
|
|
||||||
override fun toString(): String = value.toString()
|
override fun toString(): String = value.toString()
|
||||||
|
|
||||||
override val objClass: ObjClass = type
|
override val objClass: ObjClass by lazy { type }
|
||||||
|
|
||||||
override suspend fun plus(scope: Scope, other: Obj): Obj =
|
override suspend fun plus(scope: Scope, other: Obj): Obj =
|
||||||
if (other is ObjInt)
|
if (other is ObjInt)
|
||||||
|
@ -322,4 +322,9 @@ class BookTest {
|
|||||||
runDocTests("../docs/Iterable.md")
|
runDocTests("../docs/Iterable.md")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSerialization() = runBlocking {
|
||||||
|
runDocTests("../docs/serialization.md")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -649,6 +649,48 @@ class LynonTests {
|
|||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTokenFailure() = runTest {
|
||||||
|
val s = Scope()
|
||||||
|
val t = s.eval(
|
||||||
|
"""
|
||||||
|
import lyng.serialization
|
||||||
|
import lyng.buffer
|
||||||
|
import lyng.time
|
||||||
|
|
||||||
|
class Wallet( id, ownerKey, balance=0, createdAt=Instant.now().truncateToSecond(), isBlocked=false) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create new key for the given owner multikey
|
||||||
|
*/
|
||||||
|
static fun new( ownerKey ) {
|
||||||
|
|
||||||
|
// this is per-contract unique id generated and approved by the network.
|
||||||
|
// it is not random, but it _is_ unique, and we use it as a walletId.
|
||||||
|
val newId = Buffer("testid")
|
||||||
|
|
||||||
|
val w = Wallet(newId, ownerKey)
|
||||||
|
println(w)
|
||||||
|
println(w.balance)
|
||||||
|
|
||||||
|
val x = Lynon.encode(Wallet(newId, ownerKey) ).toBuffer()
|
||||||
|
val t = Lynon.decode(x.toBitInput())
|
||||||
|
println(x)
|
||||||
|
println(t)
|
||||||
|
assertEquals(w.balance, t.balance)
|
||||||
|
w
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Wallet.new(Buffer("1234"))
|
||||||
|
|
||||||
|
""".trimIndent())
|
||||||
|
println(t)
|
||||||
|
// val bb = lynonEncodeAny(s, t)
|
||||||
|
// val t2 = lynonDecodeAny(s, bb)
|
||||||
|
// println(t2.readField(s, "balance"))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user