nrser 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
- data/lib/nrser/char.rb +0 -6
- data/lib/nrser/core_ext/array.rb +120 -0
- data/lib/nrser/core_ext/binding.rb +44 -0
- data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
- data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
- data/lib/nrser/core_ext/exception.rb +30 -0
- data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
- data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
- data/lib/nrser/core_ext/hash.rb +50 -0
- data/lib/nrser/core_ext/module/method_objects.rb +96 -0
- data/lib/nrser/core_ext/module/names.rb +69 -0
- data/lib/nrser/core_ext/module/source_locations.rb +214 -0
- data/lib/nrser/core_ext/module.rb +2 -0
- data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
- data/lib/nrser/core_ext/object.rb +46 -0
- data/lib/nrser/core_ext/open_struct.rb +6 -0
- data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
- data/lib/nrser/{ext → core_ext}/string.rb +6 -12
- data/lib/nrser/core_ext/symbol.rb +13 -0
- data/lib/nrser/core_ext/time.rb +46 -0
- data/lib/nrser/core_ext.rb +13 -0
- data/lib/nrser/errors/abstract_method_error.rb +150 -0
- data/lib/nrser/errors/argument_error.rb +42 -0
- data/lib/nrser/errors/nicer_error.rb +298 -72
- data/lib/nrser/errors/type_error.rb +46 -0
- data/lib/nrser/errors.rb +4 -53
- data/lib/nrser/ext/tree.rb +3 -0
- data/lib/nrser/functions/enumerable/associate.rb +6 -9
- data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
- data/lib/nrser/functions/enumerable.rb +1 -3
- data/lib/nrser/functions/exception.rb +1 -1
- data/lib/nrser/functions/hash.rb +0 -6
- data/lib/nrser/functions/merge_by.rb +2 -2
- data/lib/nrser/functions/module/method_objects.rb +77 -0
- data/lib/nrser/functions/module.rb +1 -2
- data/lib/nrser/functions/open_struct.rb +25 -35
- data/lib/nrser/functions/proc.rb +1 -6
- data/lib/nrser/functions/string/looks_like.rb +32 -1
- data/lib/nrser/functions/string.rb +1 -40
- data/lib/nrser/functions/text/lines.rb +2 -1
- data/lib/nrser/functions.rb +0 -1
- data/lib/nrser/graph/tsorter.rb +41 -0
- data/lib/nrser/labs/core_ext/binding.rb +37 -0
- data/lib/nrser/labs/stash.rb +372 -0
- data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
- data/lib/nrser/log/appender.rb +3 -0
- data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
- data/lib/nrser/log/formatters/mixin.rb +270 -0
- data/lib/nrser/{logging → log}/formatters.rb +0 -0
- data/lib/nrser/log/logger.rb +229 -0
- data/lib/nrser/log/mixin.rb +56 -0
- data/lib/nrser/log.rb +723 -0
- data/lib/nrser/message.rb +24 -3
- data/lib/nrser/meta/source/location.rb +158 -0
- data/lib/nrser/meta.rb +1 -1
- data/lib/nrser/props/class_methods.rb +118 -0
- data/lib/nrser/props/immutable/hash.rb +111 -0
- data/lib/nrser/props/immutable/hash_variable.rb +82 -0
- data/lib/nrser/props/immutable/instance_variables.rb +48 -0
- data/lib/nrser/props/immutable/vector.rb +107 -0
- data/lib/nrser/props/instance_methods.rb +184 -0
- data/lib/nrser/props/metadata.rb +359 -0
- data/lib/nrser/props/mutable/instance_variables.rb +60 -0
- data/lib/nrser/props/mutable/stash.rb +199 -0
- data/lib/nrser/{meta/props → props}/prop.rb +217 -112
- data/lib/nrser/props/storage/instance_variable.rb +85 -0
- data/lib/nrser/props/storage/instance_variables.rb +67 -0
- data/lib/nrser/props/storage/key.rb +88 -0
- data/lib/nrser/props.rb +9 -0
- data/lib/nrser/refinements/sugar.rb +41 -0
- data/lib/nrser/refinements/types.rb +2 -2
- data/lib/nrser/refinements.rb +14 -16
- data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
- data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
- data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
- data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
- data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
- data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
- data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
- data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
- data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
- data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
- data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
- data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
- data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
- data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
- data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
- data/lib/nrser/rspex/example_group/overrides.rb +66 -0
- data/lib/nrser/rspex/example_group.rb +20 -252
- data/lib/nrser/rspex/format.rb +83 -17
- data/lib/nrser/rspex.rb +4 -34
- data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
- data/lib/nrser/{env → sys/env}/path.rb +1 -2
- data/lib/nrser/{env.rb → sys/env.rb} +2 -1
- data/lib/nrser/sys.rb +5 -0
- data/lib/nrser/types/any.rb +36 -7
- data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
- data/lib/nrser/types/attrs.rb +68 -15
- data/lib/nrser/types/booleans.rb +95 -34
- data/lib/nrser/types/bounded.rb +12 -10
- data/lib/nrser/types/combinators.rb +74 -37
- data/lib/nrser/types/errors/check_error.rb +86 -0
- data/lib/nrser/types/errors/from_string_error.rb +82 -0
- data/lib/nrser/types/factory.rb +91 -0
- data/lib/nrser/types/hashes.rb +171 -26
- data/lib/nrser/types/in.rb +25 -12
- data/lib/nrser/types/is.rb +50 -18
- data/lib/nrser/types/is_a.rb +52 -33
- data/lib/nrser/types/labels.rb +6 -33
- data/lib/nrser/types/maybe.rb +12 -4
- data/lib/nrser/types/nil.rb +24 -4
- data/lib/nrser/types/not.rb +6 -16
- data/lib/nrser/types/numbers.rb +94 -57
- data/lib/nrser/types/pairs.rb +57 -57
- data/lib/nrser/types/paths.rb +112 -133
- data/lib/nrser/types/responds.rb +64 -74
- data/lib/nrser/types/shape.rb +29 -24
- data/lib/nrser/types/strings.rb +25 -17
- data/lib/nrser/types/symbols.rb +19 -17
- data/lib/nrser/types/trees.rb +18 -70
- data/lib/nrser/types/tuples.rb +36 -40
- data/lib/nrser/types/type.rb +342 -91
- data/lib/nrser/types/when.rb +40 -18
- data/lib/nrser/types/where.rb +94 -9
- data/lib/nrser/types.rb +72 -63
- data/lib/nrser/version.rb +1 -1
- data/lib/nrser.rb +18 -18
- data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
- data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
- data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
- data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
- data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
- data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
- data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
- data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
- data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
- data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
- data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
- data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
- data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
- data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
- data/spec/lib/nrser/refinements/array_spec.rb +2 -15
- data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
- data/spec/lib/nrser/refinements/set_spec.rb +2 -15
- data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
- data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
- data/spec/lib/nrser/types/array_spec.rb +8 -8
- data/spec/lib/nrser/types/paths_spec.rb +15 -18
- data/spec/spec_helper.rb +4 -0
- metadata +109 -69
- data/lib/nrser/ext/binding.rb +0 -36
- data/lib/nrser/ext/module.rb +0 -62
- data/lib/nrser/ext.rb +0 -8
- data/lib/nrser/functions/binding.rb +0 -76
- data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
- data/lib/nrser/functions/enumerable/map_values.rb +0 -94
- data/lib/nrser/functions/hash/deep_merge.rb +0 -57
- data/lib/nrser/functions/hash/except_keys.rb +0 -44
- data/lib/nrser/functions/hash/slice_keys.rb +0 -43
- data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
- data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
- data/lib/nrser/functions/hash/transform_keys.rb +0 -140
- data/lib/nrser/functions/module/methods.rb +0 -206
- data/lib/nrser/functions/module/source_locations.rb +0 -213
- data/lib/nrser/logging/appender.rb +0 -3
- data/lib/nrser/logging.rb +0 -353
- data/lib/nrser/meta/props/base.rb +0 -31
- data/lib/nrser/meta/props.rb +0 -357
- data/lib/nrser/refinements/array.rb +0 -133
- data/lib/nrser/refinements/binding.rb +0 -6
- data/lib/nrser/refinements/enumerator.rb +0 -5
- data/lib/nrser/refinements/exception.rb +0 -35
- data/lib/nrser/refinements/hash.rb +0 -150
- data/lib/nrser/refinements/module.rb +0 -5
- data/lib/nrser/refinements/object.rb +0 -42
- data/lib/nrser/refinements/open_struct.rb +0 -28
- data/lib/nrser/refinements/pathname.rb +0 -5
- data/lib/nrser/refinements/set.rb +0 -5
- data/lib/nrser/refinements/string.rb +0 -5
- data/lib/nrser/refinements/symbol.rb +0 -20
- data/lib/nrser/rspex/described.rb +0 -99
- data/spec/design/mapping_spec.rb +0 -42
- data/spec/lib/nrser/functions/hash_spec.rb +0 -41
- data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
- data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
data/lib/nrser/message.rb
CHANGED
@@ -52,7 +52,7 @@ module NRSER
|
|
52
52
|
|
53
53
|
# Name of method the message is for.
|
54
54
|
#
|
55
|
-
# @return [Symbol
|
55
|
+
# @return [Symbol]
|
56
56
|
#
|
57
57
|
attr_reader :symbol
|
58
58
|
|
@@ -83,12 +83,33 @@ module NRSER
|
|
83
83
|
# Optional block that should be sent.
|
84
84
|
#
|
85
85
|
def initialize symbol, *args, &block
|
86
|
-
@symbol = symbol
|
86
|
+
@symbol = symbol.to_sym
|
87
87
|
@args = args
|
88
88
|
@block = block
|
89
89
|
end
|
90
90
|
|
91
91
|
|
92
|
+
def options
|
93
|
+
if args.last.is_a? Hash
|
94
|
+
args.last
|
95
|
+
else
|
96
|
+
{}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def symbolize_options
|
102
|
+
if args.last.is_a? Hash
|
103
|
+
self.class.new \
|
104
|
+
symbol,
|
105
|
+
*args[0..-2],
|
106
|
+
args.last.sym_keys
|
107
|
+
else
|
108
|
+
self
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
92
113
|
# Creates a {Proc} that accepts a single `receiver` argument and calls
|
93
114
|
# {#sent_to} on it, allowing messages to be used via the `&` operator
|
94
115
|
# in `map`, etc.
|
@@ -114,7 +135,7 @@ module NRSER
|
|
114
135
|
end
|
115
136
|
|
116
137
|
alias_method :to_sender, :to_proc
|
117
|
-
|
138
|
+
|
118
139
|
|
119
140
|
# Send this instance to a receiver object.
|
120
141
|
#
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Stdlib
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Deps
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
|
13
|
+
# Project / Package
|
14
|
+
# -----------------------------------------------------------------------
|
15
|
+
|
16
|
+
require 'nrser/props'
|
17
|
+
require 'nrser/props/immutable/vector'
|
18
|
+
|
19
|
+
|
20
|
+
# Refinements
|
21
|
+
# =======================================================================
|
22
|
+
|
23
|
+
using NRSER::Types
|
24
|
+
|
25
|
+
|
26
|
+
# Declarations
|
27
|
+
# =======================================================================
|
28
|
+
|
29
|
+
module NRSER::Meta::Source; end
|
30
|
+
|
31
|
+
|
32
|
+
# Definitions
|
33
|
+
# =======================================================================
|
34
|
+
|
35
|
+
# @todo document NRSER::Meta::Source::Location class.
|
36
|
+
#
|
37
|
+
class NRSER::Meta::Source::Location < Hamster::Vector
|
38
|
+
|
39
|
+
# Mixins
|
40
|
+
# ============================================================================
|
41
|
+
|
42
|
+
include NRSER::Props::Immutable::Vector
|
43
|
+
|
44
|
+
|
45
|
+
# Class Methods
|
46
|
+
# ============================================================================
|
47
|
+
|
48
|
+
# Given an {Enumerable} of {Method} objects, return a {Hash} mapping their
|
49
|
+
# {Method#name} to the method's {NRSER::Meta::Source::Location}.
|
50
|
+
#
|
51
|
+
# @note
|
52
|
+
# We map the names instead of the {Method} objects themselves because
|
53
|
+
# aliases produce two different {Method} objects that `#==` and `#hash`
|
54
|
+
# the same, preventing them both from being {Hash} keys.
|
55
|
+
#
|
56
|
+
# @param [Enumerable<Method>] methods
|
57
|
+
# Methods you want the source locations for.
|
58
|
+
#
|
59
|
+
# @param [Boolean] only_valid:
|
60
|
+
# When `true` filter the results to only those that are {#valid?}.
|
61
|
+
#
|
62
|
+
# @return [Hash<Symbol, NRSER::Meta::Source::Location>]
|
63
|
+
# Map of method name to their source locations.
|
64
|
+
#
|
65
|
+
def self.for_methods methods, only_valid: false
|
66
|
+
all = methods.map { |method|
|
67
|
+
[ method.name, NRSER::Meta::Source::Location.new( method ) ]
|
68
|
+
}.to_h
|
69
|
+
|
70
|
+
if only_valid
|
71
|
+
all.select { |method, location| location.valid? }
|
72
|
+
else
|
73
|
+
all
|
74
|
+
end
|
75
|
+
end # .for_methods
|
76
|
+
|
77
|
+
|
78
|
+
# Props
|
79
|
+
# ======================================================================
|
80
|
+
|
81
|
+
prop :file, type: t.abs_path?, default: nil, index: 0
|
82
|
+
prop :line, type: t.pos_int?, default: nil, index: 1
|
83
|
+
|
84
|
+
|
85
|
+
# Constructor
|
86
|
+
# ============================================================================
|
87
|
+
|
88
|
+
# Override to allow argument to be `nil` for when {Method#source_location}
|
89
|
+
# weirdly returns `nil`.
|
90
|
+
#
|
91
|
+
# @param [(#[] & (#each_pair | #each_index)) | nil ] source
|
92
|
+
# Source to construct from:
|
93
|
+
#
|
94
|
+
# 1. `#[] & (#each_pair | #each_index)`
|
95
|
+
# 1. Hash-like that responds to `#each_pair` and contains prop
|
96
|
+
# value sources keyed by their names.
|
97
|
+
#
|
98
|
+
# Supports standard propertied class construction.
|
99
|
+
#
|
100
|
+
# **Examples:**
|
101
|
+
#
|
102
|
+
# {file: '/some/abs/path.rb', line: 88}
|
103
|
+
# {file: '/some/abs/path.rb', line: nil}
|
104
|
+
# {file: nil, line: 88}
|
105
|
+
# {file: nil, line: nil}
|
106
|
+
# {}
|
107
|
+
#
|
108
|
+
# 2. Array-like that responds to `#each_index` and contains prop
|
109
|
+
# values sources indexed by their non-negative integer indexes.
|
110
|
+
#
|
111
|
+
# Supports the output of {Method#source_location}.
|
112
|
+
#
|
113
|
+
# **Examples:**
|
114
|
+
#
|
115
|
+
# ['/some/abs/path.rb', 88]
|
116
|
+
# ['/some/abs/path.rb', nil]
|
117
|
+
# [nil, 88]
|
118
|
+
# [nil, nil]
|
119
|
+
# []
|
120
|
+
#
|
121
|
+
# 2. `nil` - Swapped for `{]` to support times I'm pretty sure I've seen
|
122
|
+
# {Method#source_location} return strait-up `nil`.
|
123
|
+
#
|
124
|
+
#
|
125
|
+
def initialize source
|
126
|
+
source = source.source_location if source.respond_to? :source_location
|
127
|
+
source = {} if source.nil?
|
128
|
+
super source
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# Instance Methods
|
133
|
+
# ======================================================================
|
134
|
+
|
135
|
+
# Do we have a file and a line?
|
136
|
+
#
|
137
|
+
# Sometimes `#source_location` gives back `nil` values or just `nil`
|
138
|
+
# (in which case we set both {#file} and {#line} to `nil`). I think this
|
139
|
+
# has to do with C extensions and other weirdness.
|
140
|
+
#
|
141
|
+
# Anyways, this helps you handle it.
|
142
|
+
#
|
143
|
+
# @return [Boolean]
|
144
|
+
#
|
145
|
+
def valid?
|
146
|
+
!( file.nil? && line.nil? )
|
147
|
+
end # #valid?
|
148
|
+
|
149
|
+
|
150
|
+
# @return [String]
|
151
|
+
# a short string describing the instance.
|
152
|
+
#
|
153
|
+
def to_s
|
154
|
+
"#{ file || '???' }:#{ line || '???' }"
|
155
|
+
end # #to_s
|
156
|
+
|
157
|
+
|
158
|
+
end # class NRSER::Meta::Source::Location
|
data/lib/nrser/meta.rb
CHANGED
@@ -0,0 +1,118 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Stdlib
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Deps
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
|
13
|
+
# Project / Package
|
14
|
+
# -----------------------------------------------------------------------
|
15
|
+
require_relative './metadata'
|
16
|
+
|
17
|
+
# Refinements
|
18
|
+
# =======================================================================
|
19
|
+
|
20
|
+
|
21
|
+
# Declarations
|
22
|
+
# =======================================================================
|
23
|
+
|
24
|
+
module NRSER::Props; end
|
25
|
+
|
26
|
+
|
27
|
+
# Definitions
|
28
|
+
# =======================================================================
|
29
|
+
|
30
|
+
|
31
|
+
# Class method "macros" that are extended in to data classes, providing the
|
32
|
+
# declaration interface.
|
33
|
+
#
|
34
|
+
module NRSER::Props::ClassMethods
|
35
|
+
|
36
|
+
include NRSER::Log::Mixin
|
37
|
+
|
38
|
+
# Get the metadata object for this class, creating it if it doesn't exist.
|
39
|
+
#
|
40
|
+
# @return [NRSER::Props::Metadata]
|
41
|
+
#
|
42
|
+
def metadata
|
43
|
+
# TODO Move into {NRSER::Props::Metadata}?
|
44
|
+
#
|
45
|
+
unless NRSER::Props::Metadata.has_metadata? self
|
46
|
+
instance_variable_set \
|
47
|
+
NRSER::Props::Metadata::VARIABLE_NAME,
|
48
|
+
NRSER::Props::Metadata.new( self )
|
49
|
+
end
|
50
|
+
|
51
|
+
NRSER::Props::Metadata.metadata_for self
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def props *args, &block
|
56
|
+
metadata.props *args, &block
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def prop *args, &block
|
61
|
+
metadata.prop *args, &block
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def invariants *args, &block
|
66
|
+
metadata.invariants *args, &block
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def invariant *args, &block
|
71
|
+
metadata.invariant *args, &block
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# Instantiate from a data hash.
|
76
|
+
#
|
77
|
+
# @todo
|
78
|
+
# This needs to be extended to handle prop'd classes nested in
|
79
|
+
# arrays and hashes... but for the moment, it is what it is.
|
80
|
+
#
|
81
|
+
# This *may* have been fixed...?
|
82
|
+
#
|
83
|
+
# @param [#each_pair] data
|
84
|
+
#
|
85
|
+
# @return [self]
|
86
|
+
#
|
87
|
+
# @raise [NRSER::ArgumentError]
|
88
|
+
# If `data` does not respond to `#each_pair`.
|
89
|
+
#
|
90
|
+
def from_data data
|
91
|
+
values = {}
|
92
|
+
props = self.props
|
93
|
+
|
94
|
+
unless data.respond_to? :each_pair
|
95
|
+
raise NRSER::ArgumentError.new \
|
96
|
+
"`data` argument must respond to `#each_pair`",
|
97
|
+
data: data,
|
98
|
+
class: self
|
99
|
+
end
|
100
|
+
|
101
|
+
data.each_pair do |data_key, data_value|
|
102
|
+
prop_key = case data_key
|
103
|
+
when Symbol
|
104
|
+
data_key
|
105
|
+
when String
|
106
|
+
data_key.to_sym
|
107
|
+
end
|
108
|
+
|
109
|
+
if prop_key &&
|
110
|
+
(prop = props[prop_key])
|
111
|
+
values[prop_key] = prop.value_from_data data_value
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
self.new values
|
116
|
+
end # #from_data
|
117
|
+
|
118
|
+
end # module NRSER::Props::ClassMethods
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
require 'hamster'
|
10
|
+
|
11
|
+
# Project / Package
|
12
|
+
# -----------------------------------------------------------------------
|
13
|
+
require_relative '../storage/key'
|
14
|
+
|
15
|
+
|
16
|
+
# Declarations
|
17
|
+
# =======================================================================
|
18
|
+
|
19
|
+
module NRSER::Props::Immutable; end
|
20
|
+
|
21
|
+
|
22
|
+
# Definitions
|
23
|
+
# =======================================================================
|
24
|
+
|
25
|
+
# Mixin for classes that extend {Hamster::Hash} and will use itself as the
|
26
|
+
# property value storage.
|
27
|
+
#
|
28
|
+
module NRSER::Props::Immutable::Hash
|
29
|
+
|
30
|
+
# Constants
|
31
|
+
# ==========================================================================
|
32
|
+
|
33
|
+
STORAGE = NRSER::Props::Storage::Key.new immutable: true, key_type: :name
|
34
|
+
|
35
|
+
|
36
|
+
# Module Methods
|
37
|
+
# ======================================================================
|
38
|
+
|
39
|
+
def self.included base
|
40
|
+
unless base < Hamster::Hash
|
41
|
+
raise binding.erb <<~END
|
42
|
+
This class is only for including in {Hamster::Hash} subclasses!
|
43
|
+
END
|
44
|
+
end
|
45
|
+
|
46
|
+
base.include NRSER::Props
|
47
|
+
base.metadata.storage STORAGE
|
48
|
+
base.metadata.freeze
|
49
|
+
|
50
|
+
base.extend ClassMethods
|
51
|
+
base.include InstanceMethods
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# Mixin Methods
|
56
|
+
# ======================================================================
|
57
|
+
|
58
|
+
# Methods mixed in at the class-level.
|
59
|
+
#
|
60
|
+
module ClassMethods
|
61
|
+
# {Hamster::Hash} uses `.alloc` to quickly create derived instances
|
62
|
+
# when it knows the instance variables. We need to hook into that to
|
63
|
+
# check the prop types.
|
64
|
+
#
|
65
|
+
# @param (see Hamster::Hash.alloc)
|
66
|
+
#
|
67
|
+
# @return [Hamster::Hash]
|
68
|
+
# The new instance, which will be of the propertied subclass of
|
69
|
+
# {Hamster::Hash}.
|
70
|
+
#
|
71
|
+
# @raise [TypeError]
|
72
|
+
# If the prop values of the new vector don't satisfy the prop types.
|
73
|
+
#
|
74
|
+
def alloc *args
|
75
|
+
super( *args ).tap do |new_instance|
|
76
|
+
self.props( only_primary: true ).values.each do |prop|
|
77
|
+
prop.check! new_instance[prop.name]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end # module ClassMethods
|
82
|
+
|
83
|
+
module InstanceMethods
|
84
|
+
# Constructor
|
85
|
+
# ----------------------------------------------------------------------------
|
86
|
+
|
87
|
+
# Since including classes are using themselves as storage, we need to tap
|
88
|
+
# into the `#initialize` chain in order to load property values from sources
|
89
|
+
# and pass an {Array} up to the super-method to instantiate the
|
90
|
+
# {Hamster::Hash}.
|
91
|
+
#
|
92
|
+
def initialize values = {}
|
93
|
+
# Handles things like `[[:x, 1], [:y, 2]]`
|
94
|
+
values = values.to_h unless values.respond_to?( :each_pair )
|
95
|
+
|
96
|
+
super_values = {}
|
97
|
+
|
98
|
+
self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
|
99
|
+
super_values[prop.name] = value
|
100
|
+
}
|
101
|
+
|
102
|
+
super super_values
|
103
|
+
|
104
|
+
# Check additional type invariants
|
105
|
+
self.class.invariants.each do |type|
|
106
|
+
type.check self
|
107
|
+
end
|
108
|
+
end # #initialize
|
109
|
+
end
|
110
|
+
|
111
|
+
end # module NRSER::Props::Immutable::Hash
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Stdlib
|
5
|
+
# -----------------------------------------------------------------------
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Project / Package
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
require_relative '../storage/key'
|
13
|
+
require_relative '../storage/instance_variable'
|
14
|
+
|
15
|
+
|
16
|
+
# Declarations
|
17
|
+
# =======================================================================
|
18
|
+
|
19
|
+
module NRSER; end
|
20
|
+
module NRSER::Props; end
|
21
|
+
|
22
|
+
|
23
|
+
# Definitions
|
24
|
+
# =======================================================================
|
25
|
+
|
26
|
+
# Mix-in to store property values in an immutable {Hamster::Hash} instance
|
27
|
+
# in an instance variable.
|
28
|
+
#
|
29
|
+
# This is basically an improvement of how the original props implementation
|
30
|
+
# worked.
|
31
|
+
#
|
32
|
+
module NRSER::Props::Immutable::HashVariable
|
33
|
+
|
34
|
+
KEY_STORAGE = NRSER::Props::Storage::Key.new immutable: true, key_type: :name
|
35
|
+
|
36
|
+
INSTANCE_VARIABLE_STORAGE = \
|
37
|
+
NRSER::Props::Storage::InstanceVariable.new sub_storage: KEY_STORAGE
|
38
|
+
|
39
|
+
|
40
|
+
# Class Methods
|
41
|
+
# ======================================================================
|
42
|
+
|
43
|
+
def self.included base
|
44
|
+
base.include NRSER::Props
|
45
|
+
base.metadata.storage INSTANCE_VARIABLE_STORAGE
|
46
|
+
base.metadata.freeze
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Constructor
|
51
|
+
# ======================================================================
|
52
|
+
|
53
|
+
# Instantiate a new `NRSER::Props::Immutable::Vector`.
|
54
|
+
def initialize_props values = {}
|
55
|
+
prop_values = {}
|
56
|
+
|
57
|
+
self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
|
58
|
+
prop_values[prop.name] = value
|
59
|
+
}
|
60
|
+
|
61
|
+
instance_variable_set self.class.metadata.storage.var_name,
|
62
|
+
Hamster::Hash.new( values )
|
63
|
+
|
64
|
+
# Check additional type invariants
|
65
|
+
self.class.invariants.each do |type|
|
66
|
+
type.check self
|
67
|
+
end
|
68
|
+
end # #initialize
|
69
|
+
|
70
|
+
end # module NRSER::Props::Immutable::HashVariable
|
71
|
+
|
72
|
+
|
73
|
+
# @todo document NRSER::Props::Immutable::HashVariable::Base module.
|
74
|
+
class NRSER::Props::Immutable::HashVariable::Base
|
75
|
+
|
76
|
+
include NRSER::Props::Immutable::HashVariable
|
77
|
+
|
78
|
+
def initialize values = {}
|
79
|
+
initialize_props values
|
80
|
+
end
|
81
|
+
|
82
|
+
end # class NRSER::Props::Immutable::HashVariable::Base
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Project / Package
|
5
|
+
# -----------------------------------------------------------------------
|
6
|
+
require_relative '../../props'
|
7
|
+
require_relative '../storage/key'
|
8
|
+
require_relative '../storage/instance_variables'
|
9
|
+
|
10
|
+
|
11
|
+
# Definitions
|
12
|
+
# =======================================================================
|
13
|
+
|
14
|
+
# Mix-in to store property values in instance variables of the same name.
|
15
|
+
#
|
16
|
+
module NRSER::Props::Immutable::InstanceVariables
|
17
|
+
|
18
|
+
STORAGE = NRSER::Props::Storage::InstanceVariables.new immutable: true
|
19
|
+
|
20
|
+
|
21
|
+
# Class Methods
|
22
|
+
# ======================================================================
|
23
|
+
|
24
|
+
def self.included base
|
25
|
+
base.include NRSER::Props
|
26
|
+
base.metadata.storage STORAGE
|
27
|
+
base.metadata.freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# Instance Methods
|
32
|
+
# ======================================================================
|
33
|
+
|
34
|
+
# Since the {NRSER::Props::Immutable::InstanceVariables} mix-in does *not*
|
35
|
+
# need to tap into the initialize chain,
|
36
|
+
#
|
37
|
+
def initialize_props values = {}
|
38
|
+
self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
|
39
|
+
instance_variable_set "@#{ prop.name }", value
|
40
|
+
}
|
41
|
+
|
42
|
+
# Check additional type invariants
|
43
|
+
self.class.invariants.each do |type|
|
44
|
+
type.check self
|
45
|
+
end
|
46
|
+
end # #initialize_props
|
47
|
+
|
48
|
+
end # module NRSER::Props::Immutable
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
require 'hamster'
|
10
|
+
|
11
|
+
# Project / Package
|
12
|
+
# -----------------------------------------------------------------------
|
13
|
+
require_relative '../storage/key'
|
14
|
+
|
15
|
+
|
16
|
+
# Declarations
|
17
|
+
# =======================================================================
|
18
|
+
|
19
|
+
module NRSER::Props::Immutable; end
|
20
|
+
|
21
|
+
|
22
|
+
# Definitions
|
23
|
+
# =======================================================================
|
24
|
+
|
25
|
+
# Mixin for classes that extend {Hamster::Vector} and will use itself as the
|
26
|
+
# property value storage, requiring that property keys be non-negative
|
27
|
+
# integers.
|
28
|
+
#
|
29
|
+
module NRSER::Props::Immutable::Vector
|
30
|
+
|
31
|
+
# Constants
|
32
|
+
# ==========================================================================
|
33
|
+
|
34
|
+
STORAGE = NRSER::Props::Storage::Key.new immutable: true, key_type: :index
|
35
|
+
|
36
|
+
|
37
|
+
# Module Methods
|
38
|
+
# ======================================================================
|
39
|
+
|
40
|
+
def self.included base
|
41
|
+
unless base < Hamster::Vector
|
42
|
+
raise binding.erb <<~END
|
43
|
+
This class is only for including in {Hamster::Vector} subclasses!
|
44
|
+
END
|
45
|
+
end
|
46
|
+
|
47
|
+
base.include NRSER::Props
|
48
|
+
base.metadata.storage STORAGE
|
49
|
+
base.metadata.freeze
|
50
|
+
|
51
|
+
base.extend ClassMethods
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# Mixin Methods
|
56
|
+
# ======================================================================
|
57
|
+
|
58
|
+
# Methods mixed in at the class-level.
|
59
|
+
#
|
60
|
+
module ClassMethods
|
61
|
+
# {Hamster::Vector} uses `.alloc` to quickly create derived instances
|
62
|
+
# when it knows the instance variables. We need to hook into that to
|
63
|
+
# check the prop types.
|
64
|
+
#
|
65
|
+
# @param (see Hamster::Vector.alloc)
|
66
|
+
#
|
67
|
+
# @return [Hamster::Vector]
|
68
|
+
# The new instance, which will be of the propertied subclass of
|
69
|
+
# {Hamster::Vector}.
|
70
|
+
#
|
71
|
+
# @raise [TypeError]
|
72
|
+
# If the prop values of the new vector don't satisfy the prop types.
|
73
|
+
#
|
74
|
+
def alloc *args
|
75
|
+
super( *args ).tap do |new_instance|
|
76
|
+
self.props( only_primary: true ).each_value do |prop|
|
77
|
+
prop.check! new_instance[prop.index]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end # module ClassMethods
|
82
|
+
|
83
|
+
|
84
|
+
# Constructor
|
85
|
+
# ----------------------------------------------------------------------------
|
86
|
+
|
87
|
+
# Since including classes are using themselves as storage, we need to tap
|
88
|
+
# into the `#initialize` chain in order to load property values from sources
|
89
|
+
# and pass an {Array} up to the super-method to instantiate the
|
90
|
+
# {Hamster::Vector}.
|
91
|
+
#
|
92
|
+
def initialize values = {}
|
93
|
+
super_values = []
|
94
|
+
|
95
|
+
self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
|
96
|
+
super_values[prop.index] = value
|
97
|
+
}
|
98
|
+
|
99
|
+
super super_values
|
100
|
+
|
101
|
+
# Check additional type invariants
|
102
|
+
self.class.invariants.each do |type|
|
103
|
+
type.check self
|
104
|
+
end
|
105
|
+
end # #initialize
|
106
|
+
|
107
|
+
end # module NRSER::Props::Immutable::Vector
|