Skip to content

Commit 1a05d9b

Browse files
Modifications and Improvements
- float->int8 43.7% reduction in scheme usage case - Added contribution guidelines for contributing to the project, emphasizing human authorship and the use of AI in development. - error refactoring - added OrderedMap and other related methods, now SMap requires OrderedMap to properly encode and decode - implements MultiCheckNames with bit-level byte array, introduces SMapRepeat - MultiCheck now uses bit-packed byte arrays instead of tuple-of-bools, reducing encoded buffer size and eliminating redundant framing overhead. - Added SMapRepeat to support repeated map structures with cleaner semantics and more efficient encoding. - Added SLang and also Custom json Scheme for users
1 parent 5c6a358 commit 1a05d9b

22 files changed

Lines changed: 2553 additions & 325 deletions

.github/FUNDING.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# These are supported funding model platforms
2+
3+
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4+
patreon: # Replace with a single Patreon username
5+
open_collective: # Replace with a single Open Collective username
6+
ko_fi: # Replace with a single Ko-fi username
7+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9+
liberapay: # Replace with a single Liberapay username
10+
issuehunt: # Replace with a single IssueHunt username
11+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12+
polar: # Replace with a single Polar username
13+
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
14+
thanks_dev: # Replace with a single thanks.dev username
15+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
16+
custom: ['https://github.com/quickwritereader/PackOS#sponsorship', 'https://3xpl.com/litecoin/address/ltc1qqx8e6yl95gxlwqv52mwdt9f76euvls5fvt4ckd', ]
17+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: "[BUG]"
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**To Reproduce**
14+
Steps to reproduce the behavior:
15+
16+
**Expected behavior**
17+
A clear and concise description of what you expected to happen.
18+
19+
**Additional context**
20+
Add any other context about the problem here.

CONTRIBUTING.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Contributing to PackOS
2+
3+
We welcome contributions! To maintain the integrity and ownership of the protocol, please follow these guidelines:
4+
5+
* **Human-First Logic:** All core architectural decisions, protocol designs, and initial implementations must be authored by humans.
6+
* **Assisted Development:** AI can be used to redo, port, or refactor existing human-written logic, and it is advised to use AI for generating documentation and issues.
7+
* **Transparency:** When submitting a Pull Request, please note if AI was used for scaffolding or refactoring to help maintain clear attribution history.
8+
9+
---

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,58 @@ expectedFlat := map[string]any{
318318
fmt.Println("DecodedFlat:", decodedFlat)
319319
```
320320

321+
```go
322+
// Encode with schema example
323+
expected := pack.Pack(
324+
pack.PackTuple(
325+
pack.PackInt32(2025),
326+
pack.PackBool(false),
327+
pack.PackString("az"),
328+
),
329+
pack.PackTuple(
330+
pack.PackInt16(7),
331+
pack.PackBool(true),
332+
pack.PackString("go"),
333+
),
334+
)
335+
336+
// Schema with named tuples
337+
chain := SchemeNamedChain{
338+
SchemeChain: SChain(
339+
STupleNamed(
340+
[]string{"year", "flag", "code"},
341+
SInt32,
342+
SBool,
343+
SStringLen(len("az")),
344+
),
345+
STupleNamed(
346+
[]string{"num", "flag", "lang"},
347+
SInt16,
348+
SBool,
349+
SStringLen(len("go")),
350+
),
351+
),
352+
FieldNames: []string{"firstTuple", "secondTuple"},
353+
}
354+
355+
// Value to encode: map with named fields
356+
val := map[string]any{
357+
"firstTuple": map[string]any{
358+
"year": int32(2025),
359+
"flag": false,
360+
"code": "az",
361+
},
362+
"secondTuple": map[string]any{
363+
"num": int16(7),
364+
"flag": true,
365+
"lang": "go",
366+
},
367+
}
368+
369+
actual, err := EncodeValueNamed(val, chain)
370+
fmt.Println("Encoded Named:", actual)
371+
```
372+
321373
```go
322374
// Define scheme in JSON form
323375
schemeJSON := SchemeJSON{
@@ -362,3 +414,4 @@ STuple(
362414
)
363415

364416
```
417+

Sponsorship.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
## Sponsorship
3+
4+
5+
If you find **PackOS** useful and would like to support, you can donate via **Litecoin (LTC)**.
6+
7+
**LTC Address:** `ltc1qqx8e6yl95gxlwqv52mwdt9f76euvls5fvt4ckd`
8+
> [!IMPORTANT]
9+
> Please ensure you are sending via the **Litecoin (LTC) network** only.

access/generic_decode.go

Lines changed: 122 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ func DecodePrimitive(typ types.Type, buf []byte) (interface{}, error) {
6262
}
6363

6464
// DecodeTupleGeneric: decode a []any from the current position in a SeqGetAccess.
65-
func DecodeTupleGeneric(seq *SeqGetAccess, root bool) ([]any, error) {
65+
// If root is true, the caller already consumed the tuple header.
66+
// If ordered is true, maps inside the tuple are decoded as *types.OrderedMapAny.
67+
func DecodeTupleGeneric(seq *SeqGetAccess, root bool, ordered bool) ([]any, error) {
6668
nested := seq
67-
pos := 0
6869
if !root {
69-
7070
pos := seq.CurrentIndex()
7171
typ, width, err := seq.PeekTypeWidth()
7272
if err != nil {
@@ -82,57 +82,66 @@ func DecodeTupleGeneric(seq *SeqGetAccess, root bool) ([]any, error) {
8282
}
8383
return nil, nil
8484
}
85-
8685
nested, err = seq.PeekNestedSeq()
8786
if err != nil {
8887
return nil, fmt.Errorf("DecodeTuple: nested peek failed at pos %d: %w", pos, err)
8988
}
9089
}
90+
9191
out := make([]any, 0, nested.ArgCount())
9292
for i := 0; i < nested.ArgCount(); i++ {
9393
valTyp, _, err := nested.PeekTypeWidth()
94-
9594
if err != nil {
96-
return nil, fmt.Errorf("DecodeMapAny: nested value decode error at %d: %w", i+1, err)
97-
95+
return nil, fmt.Errorf("DecodeTuple: nested value peek error at %d: %w", i, err)
9896
}
9997
switch valTyp {
10098
case types.TypeMap:
101-
v, err := DecodeMapAny(nested) // delegate
99+
var v any
100+
if ordered {
101+
v, err = DecodeOrderedMapAny(nested)
102+
} else {
103+
v, err = DecodeMapAny(nested)
104+
}
102105
if err != nil {
103-
return nil, fmt.Errorf("DecodeMapAny: nested value decode error at %d: %w", i+1, err)
106+
return nil, fmt.Errorf("DecodeTuple: nested map decode error at %d: %w", i, err)
104107
}
105108
out = append(out, v)
109+
106110
case types.TypeTuple:
107-
v, err := DecodeTuple(nested) // delegate
111+
v, err := DecodeTuple(nested)
108112
if err != nil {
109-
return nil, fmt.Errorf("DecodeMapAny: nested value decode error at %d: %w", i+1, err)
113+
return nil, fmt.Errorf("DecodeTuple: nested tuple decode error at %d: %w", i, err)
110114
}
111115
out = append(out, v)
116+
112117
default:
113118
valPayload, valTyp, err := nested.Next()
114119
if err != nil {
115-
return nil, fmt.Errorf("DecodeMapAny: nested value decode error at %d: %w", i+1, err)
120+
return nil, fmt.Errorf("DecodeTuple: nested value next error at %d: %w", i, err)
116121
}
117122
v, err := DecodePrimitive(valTyp, valPayload)
118-
119123
if err != nil {
120-
return nil, fmt.Errorf("DecodeMapAny: nested value decode error at %d: %w", i+1, err)
124+
return nil, fmt.Errorf("DecodeTuple: primitive decode error at %d: %w", i, err)
121125
}
122126
out = append(out, v)
123127
}
124-
125128
}
129+
126130
if !root {
127131
if err := seq.Advance(); err != nil {
128-
return nil, fmt.Errorf("DecodeTuple: advance failed at pos %d: %w", pos, err)
132+
return nil, fmt.Errorf("DecodeTuple: advance failed: %w", err)
129133
}
130134
}
131135
return out, nil
132136
}
133137

138+
// Convenience wrappers
134139
func DecodeTuple(seq *SeqGetAccess) ([]any, error) {
135-
return DecodeTupleGeneric(seq, false)
140+
return DecodeTupleGeneric(seq, false, false)
141+
}
142+
143+
func DecodeTupleOrdered(seq *SeqGetAccess) ([]any, error) {
144+
return DecodeTupleGeneric(seq, false, true)
136145
}
137146

138147
// DecodeMapAny: decode a map[string]any from the current position in a SeqGetAccess.
@@ -208,15 +217,91 @@ func DecodeMapAny(seq *SeqGetAccess) (map[string]any, error) {
208217
return out, nil
209218
}
210219

220+
// DecodeOrderedMapAny decodes a map from the sequence into an OrderedMapAny,
221+
// preserving insertion order of keys.
222+
func DecodeOrderedMapAny(seq *SeqGetAccess) (*types.OrderedMapAny, error) {
223+
pos := seq.CurrentIndex()
224+
typ, width, err := seq.PeekTypeWidth()
225+
if err != nil {
226+
return nil, fmt.Errorf("DecodeOrderedMapAny: peek failed at pos %d: %w", pos, err)
227+
}
228+
if typ != types.TypeMap {
229+
return nil, fmt.Errorf("DecodeOrderedMapAny: type mismatch at pos %d — expected %v, got %v", pos, types.TypeMap, typ)
230+
}
231+
if width == 0 {
232+
// nil/empty map
233+
if err := seq.Advance(); err != nil {
234+
return nil, fmt.Errorf("DecodeOrderedMapAny: advance failed at pos %d: %w", pos, err)
235+
}
236+
return nil, nil
237+
}
238+
239+
nested, err := seq.PeekNestedSeq()
240+
if err != nil {
241+
return nil, fmt.Errorf("DecodeOrderedMapAny: nested peek failed at pos %d: %w", pos, err)
242+
}
243+
244+
out := types.NewOrderedMapAny()
245+
for i := 0; i < nested.ArgCount(); i += 2 {
246+
// key
247+
keyPayload, keyTyp, err := nested.Next()
248+
if err != nil {
249+
return nil, fmt.Errorf("DecodeOrderedMapAny: key decode error at %d: %w", i, err)
250+
}
251+
if keyTyp != types.TypeString {
252+
return nil, fmt.Errorf("DecodeOrderedMapAny: map key not string at %d, got %v", i, keyTyp)
253+
}
254+
key := string(keyPayload)
255+
256+
valTyp, _, err := nested.PeekTypeWidth()
257+
if err != nil {
258+
return nil, fmt.Errorf("DecodeOrderedMapAny: nested value decode error at %d: %w", i+1, err)
259+
}
260+
261+
switch valTyp {
262+
case types.TypeMap:
263+
v, err := DecodeOrderedMapAny(nested) // delegate recursively
264+
if err != nil {
265+
return nil, fmt.Errorf("DecodeOrderedMapAny: nested value decode error at %d: %w", i+1, err)
266+
}
267+
out.Set(key, v)
268+
269+
case types.TypeTuple:
270+
v, err := DecodeTuple(nested)
271+
if err != nil {
272+
return nil, fmt.Errorf("DecodeOrderedMapAny: nested value decode error at %d: %w", i+1, err)
273+
}
274+
out.Set(key, v)
275+
276+
default:
277+
valPayload, valTyp, err := nested.Next()
278+
if err != nil {
279+
return nil, fmt.Errorf("DecodeOrderedMapAny: nested value decode error at %d: %w", i+1, err)
280+
}
281+
v, err := DecodePrimitive(valTyp, valPayload)
282+
if err != nil {
283+
return nil, fmt.Errorf("DecodeOrderedMapAny: nested value decode error at %d: %w", i+1, err)
284+
}
285+
out.Set(key, v)
286+
}
287+
}
288+
289+
if err := seq.Advance(); err != nil {
290+
return nil, fmt.Errorf("DecodeOrderedMapAny: advance failed at pos %d: %w", pos, err)
291+
}
292+
return out, nil
293+
}
294+
211295
// Decode: convenience entry point for decoding a buffer that contains a top-level tuple.
296+
// Decode decodes a buffer into Go values.
297+
// Maps inside tuples are decoded as plain map[string]any.
212298
func Decode(buf []byte) (any, error) {
213299
seq, err := NewSeqGetAccess(buf)
214300
if err != nil {
215301
return nil, fmt.Errorf("Decode: failed to create sequence: %w", err)
216302
}
217303

218-
// delegate to tuple decoder
219-
vals, err := DecodeTupleGeneric(seq, true)
304+
vals, err := DecodeTupleGeneric(seq, true, false) // ordered=false
220305
if err != nil {
221306
return nil, fmt.Errorf("Decode: tuple decode failed: %w", err)
222307
}
@@ -225,3 +310,21 @@ func Decode(buf []byte) (any, error) {
225310
}
226311
return vals, nil
227312
}
313+
314+
// DecodeOrdered decodes a buffer into Go values.
315+
// Maps inside tuples are decoded as *types.OrderedMapAny.
316+
func DecodeOrdered(buf []byte) (any, error) {
317+
seq, err := NewSeqGetAccess(buf)
318+
if err != nil {
319+
return nil, fmt.Errorf("DecodeOrdered: failed to create sequence: %w", err)
320+
}
321+
322+
vals, err := DecodeTupleGeneric(seq, true, true) // ordered=true
323+
if err != nil {
324+
return nil, fmt.Errorf("DecodeOrdered: tuple decode failed: %w", err)
325+
}
326+
if len(vals) == 1 {
327+
return vals[0], nil
328+
}
329+
return vals, nil
330+
}

access/get.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,34 @@ func (g *GetAccess) GetMapAny(pos int) (map[string]any, error) {
419419
return out, nil
420420
}
421421

422+
// GetMapOrderedAny decodes a map at the given position into an OrderedMapAny,
423+
// preserving insertion order of keys.
424+
func (g *GetAccess) GetMapOrderedAny(pos int) (*types.OrderedMapAny, error) {
425+
tp, start, end := g.rangeAt(pos)
426+
if end < start || tp != types.TypeMap {
427+
return nil, errors.New("decode error")
428+
}
429+
if end == start {
430+
return nil, nil // nil map
431+
}
432+
433+
nested := NewGetAccess(g.buf[start:end])
434+
out := types.NewOrderedMapAny()
435+
436+
for i := 0; i < nested.argCount; i += 2 {
437+
key, err := nested.GetString(i)
438+
if err != nil {
439+
return nil, fmt.Errorf("ordered map key decode error at %d: %w", i, err)
440+
}
441+
val, err := GetAny(nested, i+1)
442+
if err != nil {
443+
return nil, fmt.Errorf("ordered map value decode error at %d: %w", i+1, err)
444+
}
445+
out.Set(key, val)
446+
}
447+
return out, nil
448+
}
449+
422450
func (g *GetAccess) GetMapStr(pos int) (map[string]string, error) {
423451
tp, start, end := g.rangeAt(pos)
424452
if end < start || tp != types.TypeMap {

0 commit comments

Comments
 (0)