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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68d81342d91b044e20a05a3b6f1529c4ecf92341
4
- data.tar.gz: f15c6928d585b0d1a8e65674d5193c69a0a47efc
3
+ metadata.gz: 70a0fcf61a81ceefc60f5553225d9e9c8aef3038
4
+ data.tar.gz: fb8276527757550144e73f69b939bdeb6038a430
5
5
  SHA512:
6
- metadata.gz: e1bc4ca7eda495fa16b92a000e41e62c017e4d1b043729e3e544f0b679dbc084b7b4ffebe7d03c1b1fdcb354f9a0d3d8aee37583730e2af552baf3aa53de90ea
7
- data.tar.gz: 21aad39051235f6bb604f7151c3912bec8ac37c93ca084a07c83aa8863360522cfd4a1f796ad1c7f0ebadbd48209fd37e11fa75c5ab5ee0d4a630f82aacdca3a
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
- record_definitions[type_signature] = RecordDefiner.new(self, base_definition: base_definition).define(&block)
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(*field_definitions.values.map { |field| field.parse(data) })
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 ||= Struct.new(*field_definitions.keys.map(&:to_sym))
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(&:width).inject(&:+)
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
@@ -1,3 +1,3 @@
1
1
  module Pikelet
2
- VERSION = "2.0.0.beta.3"
2
+ VERSION = "2.0.0.beta.4"
3
3
  end
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(:data) { "Hello world" }
5
+ let(:definer) { Pikelet::RecordDefiner.new(nil, base_definition: nil) }
6
+
7
+ let(:data) { "Hello world" }
8
+
6
9
  let(:definition) do
7
- Pikelet::RecordDefiner.new(nil, base_definition: nil).define do
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pikelet
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta.3
4
+ version: 2.0.0.beta.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Carney