cddl 0.10.2 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/cddl.gemspec +1 -1
- data/lib/base45_lite.rb +71 -0
- data/lib/cddl.rb +60 -18
- data/test-data/b64c-sloppy.cddl +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e60b48882767d7e76926473b44c79369891e4203326d4e31f5693a3819f391d
|
4
|
+
data.tar.gz: 6ed2f45e7fa8468557e73c96a4dbfdd142d65fdebeeb362efeebec8007b7948f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2124a4fc046c3dc03d007ca949e4f9191497b359fe19fafe307ed2227c4b5654d909815575504e452add310dfc8487bfc13db94794d4b6c06a7af0bb2701e55f
|
7
|
+
data.tar.gz: 8a223332d81282eb9ad651dad887579ceb7b44a01d05ccff6458e271ea999a3c5fad5f81c87a6a2ccf927307b3bb9c4e06075361b0f8fc8b02005926a3d9a5b7
|
data/cddl.gemspec
CHANGED
data/lib/base45_lite.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2022 Weihang Jian <https://tonytonyjan.net>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
# An implementation of draft-faltstrom-base45-10, see
|
24
|
+
# https://datatracker.ietf.org/doc/draft-faltstrom-base45/
|
25
|
+
module Base45Lite
|
26
|
+
class Error < ::StandardError; end
|
27
|
+
class OverflowError < Error; end
|
28
|
+
class InvalidCharacterError < Error; end
|
29
|
+
class ForbiddenLengthError < Error; end
|
30
|
+
|
31
|
+
MAX_UINT18 = 2**16 - 1
|
32
|
+
SQUARED_45 = 45**2
|
33
|
+
MAPPING = [
|
34
|
+
*'0'..'9',
|
35
|
+
*'A'..'Z',
|
36
|
+
' ', '$', '%', '*', '+', '-', '.', '/', ':'
|
37
|
+
].map!.with_index { |x, i| [i, x] }.to_h.freeze
|
38
|
+
REVERSE_MAPPING = MAPPING.invert.freeze
|
39
|
+
|
40
|
+
def self.encode(input)
|
41
|
+
sequence = []
|
42
|
+
input.unpack('n*').map! do |uint16|
|
43
|
+
i, c = uint16.divmod(45)
|
44
|
+
i, d = i.divmod(45)
|
45
|
+
_, e = i.divmod(45)
|
46
|
+
sequence.push(c, d, e)
|
47
|
+
end
|
48
|
+
if input.bytesize.odd?
|
49
|
+
i, c = input.getbyte(-1).divmod(45)
|
50
|
+
_, d = i.divmod(45)
|
51
|
+
sequence.push(c, d)
|
52
|
+
end
|
53
|
+
sequence.map!{ |n| MAPPING[n] }.join
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.decode(input)
|
57
|
+
input
|
58
|
+
.chars.map! { |c| REVERSE_MAPPING[c] || raise(InvalidCharacterError) }
|
59
|
+
.each_slice(3).map do |slice|
|
60
|
+
c, d, e = slice
|
61
|
+
raise ForbiddenLengthError if d.nil?
|
62
|
+
|
63
|
+
sum = c + d * 45
|
64
|
+
sum += e * SQUARED_45 if e
|
65
|
+
raise OverflowError if sum > MAX_UINT18
|
66
|
+
|
67
|
+
sum
|
68
|
+
end
|
69
|
+
.pack((input.length % 3).zero? ? 'n*' : "n#{input.length / 3}C")
|
70
|
+
end
|
71
|
+
end
|
data/lib/cddl.rb
CHANGED
@@ -2,11 +2,13 @@ require 'abnc'
|
|
2
2
|
require 'pp'
|
3
3
|
require 'pathname'
|
4
4
|
require 'cbor-pure' unless defined?(CBOR::Tagged)
|
5
|
+
require 'cbor-deterministic'
|
5
6
|
require 'regexp-examples'
|
6
7
|
require 'abnftt'
|
7
8
|
require 'colorize'
|
8
9
|
require 'base64'
|
9
10
|
require 'base32'
|
11
|
+
require 'base45_lite'
|
10
12
|
|
11
13
|
module CDDL
|
12
14
|
|
@@ -267,6 +269,21 @@ module CDDL
|
|
267
269
|
l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
|
268
270
|
end
|
269
271
|
|
272
|
+
def unpack_array_to_sequence(content, where)
|
273
|
+
# remove the first head
|
274
|
+
n = case content.getbyte(0) - (4 << 5)
|
275
|
+
when 0..23; 1
|
276
|
+
when 24; 2
|
277
|
+
when 25; 3
|
278
|
+
when 26; 5
|
279
|
+
when 27; 9 # unlikely :-)
|
280
|
+
else fail ".cborseq sequence for #{where} not an array"
|
281
|
+
end
|
282
|
+
content[0...n] = ''
|
283
|
+
content
|
284
|
+
end
|
285
|
+
|
286
|
+
|
270
287
|
# Memoize a bit here
|
271
288
|
|
272
289
|
REGEXP_FOR_STRING = Hash.new {|h, k|
|
@@ -561,22 +578,18 @@ module CDDL
|
|
561
578
|
end
|
562
579
|
enc = bytes ? Encoding::BINARY : Encoding::UTF_8
|
563
580
|
out.force_encoding(enc)
|
564
|
-
when :cbor, :cborseq
|
581
|
+
when :cbor, :cborseq, :cbordet, :cborseqdet
|
565
582
|
unless target == [:prim, 2]
|
566
583
|
fail "Don't know yet how to generate #{where}"
|
567
584
|
end
|
568
|
-
|
569
|
-
if conop == :
|
585
|
+
input = generate1(control)
|
586
|
+
if conop == :cbordet || conop == :cborseqdet
|
587
|
+
input = input.cbor_prepare_deterministic
|
588
|
+
end
|
589
|
+
content = CBOR::encode(input)
|
590
|
+
if conop == :cborseq || conop == :cborseqdet
|
570
591
|
# remove the first head
|
571
|
-
|
572
|
-
when 0..23; 1
|
573
|
-
when 24; 2
|
574
|
-
when 25; 3
|
575
|
-
when 26; 5
|
576
|
-
when 27; 9 # unlikely :-)
|
577
|
-
else fail "Generated .cborseq sequence for #{where} not an array"
|
578
|
-
end
|
579
|
-
content[0...n] = ''
|
592
|
+
content = unpack_array_to_sequence(content, where)
|
580
593
|
end
|
581
594
|
content
|
582
595
|
when :json
|
@@ -601,16 +614,19 @@ module CDDL
|
|
601
614
|
end
|
602
615
|
content = content.join
|
603
616
|
content
|
604
|
-
when :b64u, :
|
617
|
+
when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
618
|
+
:b45, :b32, :h32, :hex, :hexlc, :hexuc
|
605
619
|
content = generate1(control)
|
606
620
|
unless String === content
|
607
621
|
fail "Don't know yet how to generate #{where}"
|
608
622
|
end
|
609
623
|
content = case conop
|
610
|
-
when :b64u
|
624
|
+
when :b64u, :"b64u-sloppy"
|
611
625
|
Base64.urlsafe_encode64(content, padding: false)
|
612
|
-
when :b64c
|
626
|
+
when :b64c, :"b64c-sloppy"
|
613
627
|
Base64.strict_encode64(content)
|
628
|
+
when :b45
|
629
|
+
Base45Lite.encode(content)
|
614
630
|
when :b32
|
615
631
|
Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
616
632
|
Base32.encode(content).gsub("=", "")
|
@@ -1040,6 +1056,22 @@ module CDDL
|
|
1040
1056
|
ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
|
1041
1057
|
when :cborseq
|
1042
1058
|
ann if validate1((CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR), control)
|
1059
|
+
when :cbordet
|
1060
|
+
decoded = CBOR::decode(d) rescue :BAD_CBOR
|
1061
|
+
if d != decoded.to_deterministic_cbor
|
1062
|
+
@last_message = "CBOR #{d.inspect} not deterministically encoded"
|
1063
|
+
nil
|
1064
|
+
else
|
1065
|
+
ann if validate1(decoded, control)
|
1066
|
+
end
|
1067
|
+
when :cborseqdet
|
1068
|
+
decoded = CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR
|
1069
|
+
if d != unpack_array_to_sequence(decoded.to_deterministic_cbor, d.inspect)
|
1070
|
+
@last_message = "CBOR Sequence #{d.inspect} not deterministically encoded"
|
1071
|
+
nil
|
1072
|
+
else
|
1073
|
+
ann if validate1(decoded, control)
|
1074
|
+
end
|
1043
1075
|
when :json
|
1044
1076
|
ann if validate1((JSON::load(d) rescue :BAD_JSON), control)
|
1045
1077
|
when :decimal
|
@@ -1060,19 +1092,26 @@ module CDDL
|
|
1060
1092
|
else
|
1061
1093
|
fail "Don't know yet how to validate against #{where}"
|
1062
1094
|
end
|
1063
|
-
when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
|
1095
|
+
when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy", :b45, :b32, :h32, :hex, :hexlc, :hexuc
|
1064
1096
|
ann if (
|
1065
1097
|
String === d && (
|
1066
1098
|
decoded = case conop
|
1067
1099
|
when :b64u
|
1068
1100
|
/=/ !~ d &&
|
1069
1101
|
Base64.urlsafe_decode64(d)
|
1102
|
+
when :"b64u-sloppy"
|
1103
|
+
/[-_=]/ !~ d &&
|
1104
|
+
Base64.decode64(d.tr("+/", "-_"))
|
1070
1105
|
when :b64c
|
1071
1106
|
Base64.strict_decode64(d)
|
1107
|
+
when :"b64c-sloppy"
|
1108
|
+
Base64.decode64(d)
|
1072
1109
|
when :b32
|
1073
1110
|
/=/ !~ d &&
|
1074
1111
|
(Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567") &&
|
1075
1112
|
Base32.decode(d)
|
1113
|
+
when :b45
|
1114
|
+
Base45Lite.decode(d)
|
1076
1115
|
when :h32
|
1077
1116
|
/=/ !~ d &&
|
1078
1117
|
(Base32.table = "0123456789ABCDEFGHIJKLMNOPQRSTUV") &&
|
@@ -1441,11 +1480,14 @@ module CDDL
|
|
1441
1480
|
|
1442
1481
|
BRACE = {"{" => :map, "[" => :array}
|
1443
1482
|
RANGE_EXCLUDE_END = {".." => false, "..." => true}
|
1444
|
-
SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
|
1483
|
+
SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
|
1484
|
+
:cbor, :cborseq, :cbordet, :cborseqdet,
|
1485
|
+
:within, :and,
|
1445
1486
|
:default, :lt, :le, :gt, :ge, :eq, :ne,
|
1446
1487
|
:feature, :abnf, :abnfb, :det, :cat, :plus,
|
1447
1488
|
:json, :decimal, :join,
|
1448
|
-
:b64u, :
|
1489
|
+
:b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
1490
|
+
:b45, :b32, :h32, :hex, :hexlc, :hexuc,
|
1449
1491
|
]
|
1450
1492
|
|
1451
1493
|
def type1(n, canbegroup = false)
|
@@ -0,0 +1 @@
|
|
1
|
+
a = text .b64c-sloppy 'mnoabcdue=='
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cddl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carsten Bormann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cbor-diag
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- cddl.gemspec
|
120
120
|
- data/cddl.abnf
|
121
121
|
- data/prelude.cddl
|
122
|
+
- lib/base45_lite.rb
|
122
123
|
- lib/cbor-pp-play.rb
|
123
124
|
- lib/cbor-pp.rb
|
124
125
|
- lib/cddl.rb
|
@@ -133,6 +134,7 @@ files:
|
|
133
134
|
- test-data/abnf3.cddl
|
134
135
|
- test-data/ambig.cddl
|
135
136
|
- test-data/b.cddl
|
137
|
+
- test-data/b64c-sloppy.cddl
|
136
138
|
- test-data/b64c.cddl
|
137
139
|
- test-data/b64u.cddl
|
138
140
|
- test-data/badaddr.cddl
|
@@ -245,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
245
247
|
- !ruby/object:Gem::Version
|
246
248
|
version: '0'
|
247
249
|
requirements: []
|
248
|
-
rubygems_version: 3.4.
|
250
|
+
rubygems_version: 3.4.6
|
249
251
|
signing_key:
|
250
252
|
specification_version: 4
|
251
253
|
summary: CDDL generator and validator.
|