pikelet 2.0.0.beta.3 → 2.0.0.beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pikelet/file_definition.rb +5 -4
- data/lib/pikelet/record_definer.rb +4 -4
- data/lib/pikelet/record_definition.rb +26 -5
- data/lib/pikelet/version.rb +1 -1
- data/lib/pikelet.rb +2 -2
- data/spec/pikelet/record_definition_spec.rb +48 -2
- data/spec/pikelet_spec.rb +30 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70a0fcf61a81ceefc60f5553225d9e9c8aef3038
|
4
|
+
data.tar.gz: fb8276527757550144e73f69b939bdeb6038a430
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3532873fe18e685b72fe211270f08d55b343e4e5cf87d094d0ec191b21c255e57c1e5eec609f2d5d789791ecfea7b9d00652ef23c6cdf034a256866ed4631c48
|
7
|
+
data.tar.gz: e274f942d76718d17a135affafff8152299edb84a06a66aaa70d9be561fd4e2d6f7087503fe11f9c3395990c3cf5b7ebf2ea8f2084e10656117bfe136dff8a26
|
@@ -2,13 +2,14 @@ module Pikelet
|
|
2
2
|
class FileDefinition
|
3
3
|
attr_reader :base_record_definition
|
4
4
|
|
5
|
-
def initialize(&block)
|
6
|
-
@base_record_definition = RecordDefiner.new(self).define(&block)
|
5
|
+
def initialize(record_class: nil, &block)
|
6
|
+
@base_record_definition = RecordDefiner.new(self, record_class: record_class).define(&block)
|
7
7
|
end
|
8
8
|
|
9
|
-
def record(type_signature, base_definition: nil, &block)
|
9
|
+
def record(type_signature, record_class: nil, base_definition: nil, &block)
|
10
10
|
base_definition ||= base_record_definition
|
11
|
-
|
11
|
+
definer = RecordDefiner.new(self, record_class: record_class, base_definition: base_definition)
|
12
|
+
record_definitions[type_signature] = definer.define(&block)
|
12
13
|
end
|
13
14
|
|
14
15
|
def record_definitions
|
@@ -2,9 +2,9 @@ module Pikelet
|
|
2
2
|
class RecordDefiner
|
3
3
|
attr_reader :file_definition, :definition
|
4
4
|
|
5
|
-
def initialize(file_definition, base_definition: nil)
|
5
|
+
def initialize(file_definition, record_class: nil, base_definition: nil)
|
6
6
|
@file_definition = file_definition
|
7
|
-
@definition = RecordDefinition.new(file_definition, base_definition: base_definition)
|
7
|
+
@definition = RecordDefinition.new(file_definition, record_class: record_class, base_definition: base_definition)
|
8
8
|
end
|
9
9
|
|
10
10
|
def define(&block)
|
@@ -27,8 +27,8 @@ module Pikelet
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def record(type_signature, &block)
|
31
|
-
file_definition.record(type_signature, base_definition: definition, &block)
|
30
|
+
def record(type_signature, record_class: nil, &block)
|
31
|
+
file_definition.record(type_signature, record_class: record_class, base_definition: definition, &block)
|
32
32
|
end
|
33
33
|
|
34
34
|
def method_missing(method, *args, **options, &block)
|
@@ -5,13 +5,13 @@ module Pikelet
|
|
5
5
|
attr_reader :file_definition, :field_definitions
|
6
6
|
attr_writer :type_signature
|
7
7
|
|
8
|
-
def initialize(file_definition, base_definition:)
|
8
|
+
def initialize(file_definition, record_class: nil, base_definition:)
|
9
9
|
@file_definition = file_definition
|
10
10
|
@field_definitions = base_definition && base_definition.field_definitions.dup || {}
|
11
|
+
@record_class = record_class
|
11
12
|
end
|
12
13
|
|
13
14
|
def field(name, index, **options, &block)
|
14
|
-
@record_class = nil
|
15
15
|
field_definitions[name] = Pikelet::FieldDefinition.new(index, **options, &block)
|
16
16
|
end
|
17
17
|
|
@@ -27,7 +27,7 @@ module Pikelet
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def parse(data)
|
30
|
-
record_class.new(
|
30
|
+
record_class.new(parse_fields(data))
|
31
31
|
end
|
32
32
|
|
33
33
|
def format(record, width: nil)
|
@@ -38,11 +38,32 @@ module Pikelet
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def record_class
|
41
|
-
@record_class ||=
|
41
|
+
@record_class ||= default_record_class
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_record_class
|
45
|
+
Struct.new(*field_names) do
|
46
|
+
def initialize(**attributes)
|
47
|
+
# FIXME: Do we need to worry about missing attributes?
|
48
|
+
super(*attributes.values_at(*self.class.members))
|
49
|
+
end
|
50
|
+
end
|
42
51
|
end
|
43
52
|
|
44
53
|
def width
|
45
|
-
field_definitions.values.map
|
54
|
+
field_definitions.values.map { |d| d.index.max }.max + 1
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def field_names
|
60
|
+
field_definitions.keys.map(&:to_sym)
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_fields(data)
|
64
|
+
field_definitions.each_with_object({}) do |(field, definition), result|
|
65
|
+
result[field.to_sym] = definition.parse(data)
|
66
|
+
end
|
46
67
|
end
|
47
68
|
end
|
48
69
|
end
|
data/lib/pikelet/version.rb
CHANGED
data/lib/pikelet.rb
CHANGED
@@ -4,7 +4,7 @@ require "pikelet/record_definition"
|
|
4
4
|
require "pikelet/field_definition"
|
5
5
|
|
6
6
|
module Pikelet
|
7
|
-
def self.define(&block)
|
8
|
-
Pikelet::FileDefinition.new(&block)
|
7
|
+
def self.define(record_class: nil, &block)
|
8
|
+
Pikelet::FileDefinition.new(record_class: record_class, &block)
|
9
9
|
end
|
10
10
|
end
|
@@ -2,9 +2,12 @@ require "spec_helper"
|
|
2
2
|
require "pikelet"
|
3
3
|
|
4
4
|
describe Pikelet::RecordDefinition do
|
5
|
-
let(:
|
5
|
+
let(:definer) { Pikelet::RecordDefiner.new(nil, base_definition: nil) }
|
6
|
+
|
7
|
+
let(:data) { "Hello world" }
|
8
|
+
|
6
9
|
let(:definition) do
|
7
|
-
|
10
|
+
definer.define do
|
8
11
|
hello 0... 5
|
9
12
|
world 6...11
|
10
13
|
end
|
@@ -43,4 +46,47 @@ describe Pikelet::RecordDefinition do
|
|
43
46
|
its(:type_signature) { is_expected.to eq :type_signature }
|
44
47
|
end
|
45
48
|
end
|
49
|
+
|
50
|
+
describe "#width" do
|
51
|
+
subject(:width) { definition.width }
|
52
|
+
|
53
|
+
context "with contiguous fields" do
|
54
|
+
let(:definition) do
|
55
|
+
definer.define do
|
56
|
+
hello 0... 5
|
57
|
+
world 6...11
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns the width of the record" do
|
62
|
+
expect(width).to eq 11
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with overlapping fields" do
|
67
|
+
let(:definition) do
|
68
|
+
definer.define do
|
69
|
+
hello 0..6
|
70
|
+
world 4..9
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns the width of the record" do
|
75
|
+
expect(width).to eq 10
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with discontinuous fields" do
|
80
|
+
let(:definition) do
|
81
|
+
definer.define do
|
82
|
+
hello 4... 7
|
83
|
+
world 9...16
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "returns the width of the record" do
|
88
|
+
expect(width).to eq 16
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
46
92
|
end
|
data/spec/pikelet_spec.rb
CHANGED
@@ -9,6 +9,36 @@ describe Pikelet do
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
describe "custom record classes" do
|
13
|
+
let(:custom_class) do
|
14
|
+
Class.new do
|
15
|
+
attr_reader :first_name, :last_name
|
16
|
+
|
17
|
+
def initialize(**attrs)
|
18
|
+
@first_name = attrs[:first_name]
|
19
|
+
@last_name = attrs[:last_name]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:definition) do
|
25
|
+
Pikelet.define record_class: custom_class do
|
26
|
+
first_name 0...10
|
27
|
+
last_name 10...20
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:data) { [ "Nicolaus Copernicus" ] }
|
32
|
+
subject(:record) { definition.parse(data).to_a.first }
|
33
|
+
|
34
|
+
it "uses the supplied record class" do
|
35
|
+
expect(record).to be_a custom_class
|
36
|
+
end
|
37
|
+
|
38
|
+
its(:first_name) { is_expected.to eq "Nicolaus" }
|
39
|
+
its(:last_name) { is_expected.to eq "Copernicus" }
|
40
|
+
end
|
41
|
+
|
12
42
|
describe "#format" do
|
13
43
|
let(:definition) do
|
14
44
|
Pikelet.define do
|