code-ruby 3.1.2 → 4.0.0
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/VERSION +1 -1
- data/bin/code +97 -20
- data/lib/code/concerns/shared.rb +331 -15
- data/lib/code/format.rb +15 -1
- data/lib/code/network.rb +87 -0
- data/lib/code/node/call.rb +79 -2
- data/lib/code/node/call_argument.rb +14 -0
- data/lib/code/node/code.rb +5 -4
- data/lib/code/node/function_parameter.rb +7 -4
- data/lib/code/node/list.rb +29 -1
- data/lib/code/object/base_64.rb +132 -6
- data/lib/code/object/boolean.rb +60 -0
- data/lib/code/object/class.rb +138 -2
- data/lib/code/object/code.rb +111 -3
- data/lib/code/object/context.rb +57 -1
- data/lib/code/object/cryptography.rb +63 -0
- data/lib/code/object/date.rb +13339 -462
- data/lib/code/object/decimal.rb +1725 -0
- data/lib/code/object/dictionary.rb +1790 -11
- data/lib/code/object/duration.rb +28 -0
- data/lib/code/object/function.rb +261 -23
- data/lib/code/object/global.rb +534 -1
- data/lib/code/object/html.rb +179 -7
- data/lib/code/object/http.rb +244 -14
- data/lib/code/object/ics.rb +75 -13
- data/lib/code/object/identifier_list.rb +17 -2
- data/lib/code/object/integer.rb +1937 -2
- data/lib/code/object/json.rb +75 -1
- data/lib/code/object/list.rb +3383 -10
- data/lib/code/object/nothing.rb +53 -0
- data/lib/code/object/number.rb +110 -0
- data/lib/code/object/parameter.rb +140 -0
- data/lib/code/object/range.rb +576 -14
- data/lib/code/object/smtp.rb +95 -12
- data/lib/code/object/string.rb +944 -3
- data/lib/code/object/super.rb +10 -1
- data/lib/code/object/time.rb +13358 -498
- data/lib/code/object/url.rb +65 -0
- data/lib/code/object.rb +543 -0
- data/lib/code/parser.rb +161 -24
- data/lib/code-ruby.rb +3 -0
- data/lib/code.rb +30 -3
- metadata +135 -84
- data/.github/dependabot.yml +0 -15
- data/.github/workflows/ci.yml +0 -38
- data/.gitignore +0 -30
- data/.node-version +0 -1
- data/.npm-version +0 -1
- data/.prettierignore +0 -2
- data/.rspec +0 -1
- data/.rubocop.yml +0 -140
- data/.ruby-version +0 -1
- data/.tool-versions +0 -3
- data/AGENTS.md +0 -43
- data/Gemfile +0 -22
- data/Gemfile.lock +0 -292
- data/Rakefile +0 -5
- data/bin/bundle +0 -123
- data/bin/bundle-audit +0 -31
- data/bin/bundler-audit +0 -31
- data/bin/dorian +0 -31
- data/bin/rspec +0 -31
- data/bin/rubocop +0 -31
- data/bin/test +0 -5
- data/code-ruby.gemspec +0 -34
- data/docs/precedence.txt +0 -36
- data/package-lock.json +0 -14
- data/package.json +0 -7
- data/spec/bin/code_spec.rb +0 -48
- data/spec/code/format_spec.rb +0 -153
- data/spec/code/node/call_spec.rb +0 -11
- data/spec/code/object/boolean_spec.rb +0 -18
- data/spec/code/object/cryptography_spec.rb +0 -25
- data/spec/code/object/decimal_spec.rb +0 -50
- data/spec/code/object/dictionary_spec.rb +0 -98
- data/spec/code/object/function_spec.rb +0 -268
- data/spec/code/object/http_spec.rb +0 -33
- data/spec/code/object/ics_spec.rb +0 -50
- data/spec/code/object/integer_spec.rb +0 -42
- data/spec/code/object/list_spec.rb +0 -22
- data/spec/code/object/nothing_spec.rb +0 -14
- data/spec/code/object/range_spec.rb +0 -23
- data/spec/code/object/string_spec.rb +0 -26
- data/spec/code/parser/boolean_spec.rb +0 -11
- data/spec/code/parser/chained_call_spec.rb +0 -16
- data/spec/code/parser/dictionary_spec.rb +0 -18
- data/spec/code/parser/function_spec.rb +0 -16
- data/spec/code/parser/group_spec.rb +0 -11
- data/spec/code/parser/if_modifier_spec.rb +0 -18
- data/spec/code/parser/list_spec.rb +0 -17
- data/spec/code/parser/number_spec.rb +0 -11
- data/spec/code/parser/string_spec.rb +0 -20
- data/spec/code/parser_spec.rb +0 -52
- data/spec/code/type_spec.rb +0 -21
- data/spec/code_spec.rb +0 -717
- data/spec/spec_helper.rb +0 -21
- data/spec/zeitwerk/loader_spec.rb +0 -7
data/lib/code/network.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Code
|
|
4
|
+
module Network
|
|
5
|
+
BLOCKED_HOSTS = %w[
|
|
6
|
+
localhost
|
|
7
|
+
localhost.localdomain
|
|
8
|
+
].freeze
|
|
9
|
+
BLOCKED_HOST_SUFFIXES = %w[
|
|
10
|
+
.local
|
|
11
|
+
.localhost
|
|
12
|
+
].freeze
|
|
13
|
+
BLOCKED_IP_RANGES = [
|
|
14
|
+
"0.0.0.0/8",
|
|
15
|
+
"10.0.0.0/8",
|
|
16
|
+
"100.64.0.0/10",
|
|
17
|
+
"127.0.0.0/8",
|
|
18
|
+
"169.254.0.0/16",
|
|
19
|
+
"172.16.0.0/12",
|
|
20
|
+
"192.0.0.0/24",
|
|
21
|
+
"192.168.0.0/16",
|
|
22
|
+
"224.0.0.0/4",
|
|
23
|
+
"240.0.0.0/4",
|
|
24
|
+
"::/128",
|
|
25
|
+
"::1/128",
|
|
26
|
+
"64:ff9b::/96",
|
|
27
|
+
"64:ff9b:1::/48",
|
|
28
|
+
"2002::/16",
|
|
29
|
+
"fc00::/7",
|
|
30
|
+
"fe80::/10",
|
|
31
|
+
"ff00::/8"
|
|
32
|
+
].map { |range| IPAddr.new(range) }.freeze
|
|
33
|
+
|
|
34
|
+
def self.validate_public_uri!(uri, service:)
|
|
35
|
+
unless %w[http https].include?(uri.scheme)
|
|
36
|
+
raise Error, "#{service}: unsupported url scheme"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
validate_public_host!(uri.hostname, service: service).first
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.validate_public_host!(host, service:)
|
|
43
|
+
normalized_host = normalize_host(host)
|
|
44
|
+
|
|
45
|
+
if blocked_hostname?(normalized_host)
|
|
46
|
+
raise Error, "#{service}: local network requests are not allowed"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
addresses = resolved_addresses(normalized_host)
|
|
50
|
+
raise Error, "#{service}: could not resolve host" if addresses.empty?
|
|
51
|
+
|
|
52
|
+
if addresses.any? { |address| blocked_address?(address) }
|
|
53
|
+
raise Error, "#{service}: local network requests are not allowed"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
addresses
|
|
57
|
+
rescue Resolv::ResolvError, ArgumentError
|
|
58
|
+
raise Error, "#{service}: could not resolve host"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.blocked_address?(address)
|
|
62
|
+
ip = IPAddr.new(address)
|
|
63
|
+
ip = ip.native if ip.respond_to?(:ipv4_mapped?) && ip.ipv4_mapped?
|
|
64
|
+
ip = ip.native if ip.respond_to?(:ipv4_compat?) && ip.ipv4_compat?
|
|
65
|
+
|
|
66
|
+
BLOCKED_IP_RANGES.any? { |range| range.include?(ip) }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.resolved_addresses(host)
|
|
70
|
+
[IPAddr.new(host).to_s]
|
|
71
|
+
rescue ArgumentError
|
|
72
|
+
Resolv.getaddresses(host)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.normalize_host(host)
|
|
76
|
+
normalized_host = host.to_s.downcase.delete_suffix(".")
|
|
77
|
+
raise Error, "network: invalid host" if normalized_host.blank?
|
|
78
|
+
|
|
79
|
+
normalized_host
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.blocked_hostname?(host)
|
|
83
|
+
BLOCKED_HOSTS.include?(host) ||
|
|
84
|
+
BLOCKED_HOST_SUFFIXES.any? { |suffix| host.end_with?(suffix) }
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
data/lib/code/node/call.rb
CHANGED
|
@@ -36,7 +36,9 @@ class Code
|
|
|
36
36
|
arguments = []
|
|
37
37
|
|
|
38
38
|
(@arguments || []).each do |argument|
|
|
39
|
-
if argument.
|
|
39
|
+
if argument.expansion?
|
|
40
|
+
append_expanded_argument(arguments, argument, **args)
|
|
41
|
+
elsif argument.keyword?
|
|
40
42
|
if arguments.last.is_a?(Object::Dictionary)
|
|
41
43
|
arguments.last.code_merge!(argument.evaluate(**args))
|
|
42
44
|
else
|
|
@@ -51,7 +53,17 @@ class Code
|
|
|
51
53
|
|
|
52
54
|
name = Object::String.new(@name)
|
|
53
55
|
|
|
54
|
-
args.fetch(:object)
|
|
56
|
+
object = args.fetch(:object)
|
|
57
|
+
dynamic_result = object.code_dynamic_call(
|
|
58
|
+
name,
|
|
59
|
+
operator: name,
|
|
60
|
+
arguments: Object::List.new(arguments),
|
|
61
|
+
explicit_arguments: @explicit_arguments,
|
|
62
|
+
**args
|
|
63
|
+
)
|
|
64
|
+
return dynamic_result if dynamic_result
|
|
65
|
+
|
|
66
|
+
object.call(
|
|
55
67
|
operator: name,
|
|
56
68
|
arguments: Object::List.new(arguments),
|
|
57
69
|
explicit_arguments: @explicit_arguments,
|
|
@@ -62,6 +74,71 @@ class Code
|
|
|
62
74
|
def resolve(**_args)
|
|
63
75
|
Object::String.new(@name)
|
|
64
76
|
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def append_expanded_argument(arguments, argument, **args)
|
|
81
|
+
value =
|
|
82
|
+
if argument.value?
|
|
83
|
+
argument.evaluate(**args)
|
|
84
|
+
else
|
|
85
|
+
default_forwarded_argument(argument.operator, args.fetch(:context))
|
|
86
|
+
end
|
|
87
|
+
return if value.nil?
|
|
88
|
+
|
|
89
|
+
case argument.operator
|
|
90
|
+
when "*", "&&"
|
|
91
|
+
value.to_code.code_to_list.raw.each { |item| arguments << item }
|
|
92
|
+
when "**"
|
|
93
|
+
dictionary = value.to_code.code_to_dictionary
|
|
94
|
+
if arguments.last.is_a?(Object::Dictionary)
|
|
95
|
+
arguments.last.code_merge!(dictionary)
|
|
96
|
+
else
|
|
97
|
+
arguments << dictionary
|
|
98
|
+
end
|
|
99
|
+
when "&"
|
|
100
|
+
code_value = value.to_code
|
|
101
|
+
arguments << if code_value.is_a?(Object::Function) ||
|
|
102
|
+
code_value.nothing?
|
|
103
|
+
code_value
|
|
104
|
+
else
|
|
105
|
+
code_value.call(operator: "&", **args)
|
|
106
|
+
end
|
|
107
|
+
when "..."
|
|
108
|
+
expanded_arguments(value, args.fetch(:context)).each do |item|
|
|
109
|
+
arguments << item
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def default_forwarded_argument(operator, context)
|
|
115
|
+
case operator
|
|
116
|
+
when "*"
|
|
117
|
+
context_fetch(context, "arguments") || Object::List.new
|
|
118
|
+
when "**"
|
|
119
|
+
context_fetch(context, "keyword_arguments")
|
|
120
|
+
when "&"
|
|
121
|
+
context_fetch(context, "block")
|
|
122
|
+
when "&&"
|
|
123
|
+
context_fetch(context, "blocks") || Object::List.new
|
|
124
|
+
when "..."
|
|
125
|
+
context_fetch(context, "rest") || Object::List.new
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def context_fetch(context, name)
|
|
130
|
+
context.code_lookup!(name).code_fetch(name)
|
|
131
|
+
rescue Error
|
|
132
|
+
nil
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def expanded_arguments(value, context)
|
|
136
|
+
if value.nothing?
|
|
137
|
+
context.code_lookup!("rest").code_fetch("rest").code_to_list.raw
|
|
138
|
+
else
|
|
139
|
+
value.to_code.code_to_list.raw
|
|
140
|
+
end
|
|
141
|
+
end
|
|
65
142
|
end
|
|
66
143
|
end
|
|
67
144
|
end
|
|
@@ -6,8 +6,10 @@ class Code
|
|
|
6
6
|
def initialize(parsed)
|
|
7
7
|
return if parsed.blank?
|
|
8
8
|
|
|
9
|
+
@has_value = parsed[:value].present?
|
|
9
10
|
@value = Node::Code.new(parsed.delete(:value).presence)
|
|
10
11
|
@name = parsed.delete(:name).presence
|
|
12
|
+
@operator = parsed.delete(:operator).presence
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def evaluate(**args)
|
|
@@ -20,10 +22,22 @@ class Code
|
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
def operator
|
|
26
|
+
@operator.to_s
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def expansion?
|
|
30
|
+
operator.present?
|
|
31
|
+
end
|
|
32
|
+
|
|
23
33
|
def keyword?
|
|
24
34
|
!!@name
|
|
25
35
|
end
|
|
26
36
|
|
|
37
|
+
def value?
|
|
38
|
+
!!@has_value
|
|
39
|
+
end
|
|
40
|
+
|
|
27
41
|
def regular?
|
|
28
42
|
!keyword?
|
|
29
43
|
end
|
data/lib/code/node/code.rb
CHANGED
|
@@ -19,13 +19,13 @@ class Code
|
|
|
19
19
|
args.merge(global_control_flow_root: false)
|
|
20
20
|
else
|
|
21
21
|
args
|
|
22
|
-
|
|
22
|
+
end
|
|
23
23
|
last = Object::Nothing.new
|
|
24
|
+
root_object = args.fetch(:root_object, args.fetch(:object))
|
|
24
25
|
|
|
25
26
|
begin
|
|
26
27
|
(@statements || []).each do |statement|
|
|
27
|
-
last =
|
|
28
|
-
statement.evaluate(**statement_args, object: Object::Global.new)
|
|
28
|
+
last = statement.evaluate(**statement_args, object: root_object)
|
|
29
29
|
end
|
|
30
30
|
rescue Error::Retry
|
|
31
31
|
retry if control_flow_scope == :group
|
|
@@ -48,9 +48,10 @@ class Code
|
|
|
48
48
|
|
|
49
49
|
def resolve(**args)
|
|
50
50
|
last = Object::Nothing.new
|
|
51
|
+
root_object = args.fetch(:root_object, args.fetch(:object))
|
|
51
52
|
|
|
52
53
|
(@statements || []).each do |statement|
|
|
53
|
-
last = statement.resolve(**args, object:
|
|
54
|
+
last = statement.resolve(**args, object: root_object)
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
last
|
|
@@ -8,15 +8,13 @@ class Code
|
|
|
8
8
|
def initialize(parsed)
|
|
9
9
|
return if parsed.blank?
|
|
10
10
|
|
|
11
|
-
@name =
|
|
12
|
-
parsed.delete(:name).presence || parsed[:regular_splat].presence ||
|
|
13
|
-
parsed[:keyword_splat].presence || parsed[:spread].presence ||
|
|
14
|
-
parsed[:block].presence
|
|
11
|
+
@name = parsed.delete(:name).presence
|
|
15
12
|
@keyword = parsed.delete(:keyword).present?
|
|
16
13
|
@regular_splat = parsed.delete(:regular_splat).present?
|
|
17
14
|
@keyword_splat = parsed.delete(:keyword_splat).present?
|
|
18
15
|
@spread = parsed.delete(:spread).present?
|
|
19
16
|
@block = parsed.delete(:block).present?
|
|
17
|
+
@blocks = parsed.delete(:blocks).present?
|
|
20
18
|
@default = Code.new(parsed.delete(:default)) if parsed.key?(:default)
|
|
21
19
|
end
|
|
22
20
|
|
|
@@ -48,6 +46,10 @@ class Code
|
|
|
48
46
|
!!@block
|
|
49
47
|
end
|
|
50
48
|
|
|
49
|
+
def blocks?
|
|
50
|
+
!!@blocks
|
|
51
|
+
end
|
|
52
|
+
|
|
51
53
|
def to_h
|
|
52
54
|
{
|
|
53
55
|
name: name,
|
|
@@ -57,6 +59,7 @@ class Code
|
|
|
57
59
|
keyword_splat?: keyword_splat?,
|
|
58
60
|
spread?: spread?,
|
|
59
61
|
block?: block?,
|
|
62
|
+
blocks?: blocks?,
|
|
60
63
|
default: default
|
|
61
64
|
}
|
|
62
65
|
end
|
data/lib/code/node/list.rb
CHANGED
|
@@ -11,9 +11,37 @@ class Code
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def evaluate(**args)
|
|
14
|
-
::Code::Object::List.new(
|
|
14
|
+
list = ::Code::Object::List.new(
|
|
15
15
|
(@elements || []).map { |element| element.evaluate(**args) }
|
|
16
16
|
)
|
|
17
|
+
constructor = literal_constructor(args.fetch(:context), "List")
|
|
18
|
+
return list unless constructor
|
|
19
|
+
return list if Array(args[:constructing_literal_classes]).include?(
|
|
20
|
+
::Code::Object::List
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
constructor.call(
|
|
24
|
+
**args,
|
|
25
|
+
constructing_literal_classes:
|
|
26
|
+
Array(args[:constructing_literal_classes]) +
|
|
27
|
+
[::Code::Object::List],
|
|
28
|
+
operator: nil,
|
|
29
|
+
arguments: ::Code::Object::List.new([list]),
|
|
30
|
+
explicit_arguments: true
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def literal_constructor(context, name)
|
|
37
|
+
return unless context.code_has_key?(name).truthy?
|
|
38
|
+
|
|
39
|
+
constructor = context.code_fetch(name)
|
|
40
|
+
return unless constructor.is_a?(::Code::Object::Function)
|
|
41
|
+
return unless constructor.parent.is_a?(::Code::Object::Class)
|
|
42
|
+
return unless constructor.parent.raw == ::Code::Object::List
|
|
43
|
+
|
|
44
|
+
constructor
|
|
17
45
|
end
|
|
18
46
|
end
|
|
19
47
|
end
|
data/lib/code/object/base_64.rb
CHANGED
|
@@ -3,28 +3,154 @@
|
|
|
3
3
|
class Code
|
|
4
4
|
class Object
|
|
5
5
|
class Base64 < Object
|
|
6
|
+
CLASS_DOCUMENTATION = {
|
|
7
|
+
name: "Base64",
|
|
8
|
+
description: "encodes and decodes strings with base64 text formats.",
|
|
9
|
+
examples: [
|
|
10
|
+
"Base64.encode(:hello)",
|
|
11
|
+
"Base64.decode(Base64.encode(:hello))",
|
|
12
|
+
"Base64.urlsafe_decode(Base64.urlsafe_encode(\"???\"))"
|
|
13
|
+
]
|
|
14
|
+
}.freeze
|
|
15
|
+
CLASS_FUNCTIONS = {
|
|
16
|
+
"encode" => {
|
|
17
|
+
name: "encode",
|
|
18
|
+
description: "returns base64 text with line breaks for a string.",
|
|
19
|
+
examples: [
|
|
20
|
+
"Base64.encode(:hello)",
|
|
21
|
+
"Base64.encode(:hello_world)",
|
|
22
|
+
"Base64.encode(\"123\")"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"encode_64" => {
|
|
26
|
+
name: "encode_64",
|
|
27
|
+
description: "returns base64 text with line breaks for a string.",
|
|
28
|
+
examples: [
|
|
29
|
+
"Base64.encode_64(:hello)",
|
|
30
|
+
"Base64.encode_64(:hello_world)",
|
|
31
|
+
"Base64.encode_64(\"123\")"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"decode" => {
|
|
35
|
+
name: "decode",
|
|
36
|
+
description: "returns a string decoded from base64 text.",
|
|
37
|
+
examples: [
|
|
38
|
+
"Base64.decode(\"aGVsbG8=\")",
|
|
39
|
+
"Base64.decode(Base64.encode(:hello))",
|
|
40
|
+
"Base64.decode(\"MTIz\")"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"decode_64" => {
|
|
44
|
+
name: "decode_64",
|
|
45
|
+
description: "returns a string decoded from base64 text.",
|
|
46
|
+
examples: [
|
|
47
|
+
"Base64.decode_64(\"aGVsbG8=\")",
|
|
48
|
+
"Base64.decode_64(Base64.encode(:hello))",
|
|
49
|
+
"Base64.decode_64(\"MTIz\")"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"strict_encode" => {
|
|
53
|
+
name: "strict_encode",
|
|
54
|
+
description: "returns base64 text without line breaks for a string.",
|
|
55
|
+
examples: [
|
|
56
|
+
"Base64.strict_encode(:hello)",
|
|
57
|
+
"Base64.strict_encode(:hello_world)",
|
|
58
|
+
"Base64.strict_encode(\"123\")"
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"strict_encode_64" => {
|
|
62
|
+
name: "strict_encode_64",
|
|
63
|
+
description: "returns base64 text without line breaks for a string.",
|
|
64
|
+
examples: [
|
|
65
|
+
"Base64.strict_encode_64(:hello)",
|
|
66
|
+
"Base64.strict_encode_64(:hello_world)",
|
|
67
|
+
"Base64.strict_encode_64(\"123\")"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"strict_decode" => {
|
|
71
|
+
name: "strict_decode",
|
|
72
|
+
description: "returns a string decoded from strict base64 text.",
|
|
73
|
+
examples: [
|
|
74
|
+
"Base64.strict_decode(\"aGVsbG8=\")",
|
|
75
|
+
"Base64.strict_decode(Base64.strict_encode(:hello))",
|
|
76
|
+
"Base64.strict_decode(\"MTIz\")"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"strict_decode_64" => {
|
|
80
|
+
name: "strict_decode_64",
|
|
81
|
+
description: "returns a string decoded from strict base64 text.",
|
|
82
|
+
examples: [
|
|
83
|
+
"Base64.strict_decode_64(\"aGVsbG8=\")",
|
|
84
|
+
"Base64.strict_decode_64(Base64.strict_encode(:hello))",
|
|
85
|
+
"Base64.strict_decode_64(\"MTIz\")"
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"urlsafe_encode" => {
|
|
89
|
+
name: "urlsafe_encode",
|
|
90
|
+
description: "returns url-safe base64 text for a string.",
|
|
91
|
+
examples: [
|
|
92
|
+
"Base64.urlsafe_encode(:hello)",
|
|
93
|
+
"Base64.urlsafe_encode(\">>>\")",
|
|
94
|
+
"Base64.urlsafe_encode(\"???\")"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
"url_safe_encode_64" => {
|
|
98
|
+
name: "url_safe_encode_64",
|
|
99
|
+
description: "returns url-safe base64 text for a string.",
|
|
100
|
+
examples: [
|
|
101
|
+
"Base64.url_safe_encode_64(:hello)",
|
|
102
|
+
"Base64.url_safe_encode_64(\">>>\")",
|
|
103
|
+
"Base64.url_safe_encode_64(\"???\")"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"urlsafe_decode" => {
|
|
107
|
+
name: "urlsafe_decode",
|
|
108
|
+
description: "returns a string decoded from url-safe base64 text.",
|
|
109
|
+
examples: [
|
|
110
|
+
"Base64.urlsafe_decode(\"aGVsbG8=\")",
|
|
111
|
+
"Base64.urlsafe_decode(\"Pj4-\")",
|
|
112
|
+
"Base64.urlsafe_decode(\"Pz8_\")"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
"url_safe_decode_64" => {
|
|
116
|
+
name: "url_safe_decode_64",
|
|
117
|
+
description: "returns a string decoded from url-safe base64 text.",
|
|
118
|
+
examples: [
|
|
119
|
+
"Base64.url_safe_decode_64(\"aGVsbG8=\")",
|
|
120
|
+
"Base64.url_safe_decode_64(\"Pj4-\")",
|
|
121
|
+
"Base64.url_safe_decode_64(\"Pz8_\")"
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
}.freeze
|
|
125
|
+
|
|
126
|
+
def self.function_documentation(scope)
|
|
127
|
+
return CLASS_FUNCTIONS if scope == :class
|
|
128
|
+
|
|
129
|
+
{}
|
|
130
|
+
end
|
|
131
|
+
|
|
6
132
|
def self.call(**args)
|
|
7
133
|
code_operator = args.fetch(:operator, nil).to_code
|
|
8
134
|
code_arguments = args.fetch(:arguments, []).to_code
|
|
9
135
|
code_value = code_arguments.code_first
|
|
10
136
|
|
|
11
137
|
case code_operator.to_s
|
|
12
|
-
when "encode"
|
|
138
|
+
when "encode", "encode_64"
|
|
13
139
|
sig(args) { String }
|
|
14
140
|
code_encode(code_value)
|
|
15
|
-
when "decode"
|
|
141
|
+
when "decode", "decode_64"
|
|
16
142
|
sig(args) { String }
|
|
17
143
|
code_decode(code_value)
|
|
18
|
-
when "strict_encode"
|
|
144
|
+
when "strict_encode", "strict_encode_64"
|
|
19
145
|
sig(args) { String }
|
|
20
146
|
code_strict_encode(code_value)
|
|
21
|
-
when "strict_decode"
|
|
147
|
+
when "strict_decode", "strict_decode_64"
|
|
22
148
|
sig(args) { String }
|
|
23
149
|
code_strict_decode(code_value)
|
|
24
|
-
when "urlsafe_encode"
|
|
150
|
+
when "urlsafe_encode", "url_safe_encode_64"
|
|
25
151
|
sig(args) { String }
|
|
26
152
|
code_urlsafe_encode(code_value)
|
|
27
|
-
when "urlsafe_decode"
|
|
153
|
+
when "urlsafe_decode", "url_safe_decode_64"
|
|
28
154
|
sig(args) { String }
|
|
29
155
|
code_urlsafe_decode(code_value)
|
|
30
156
|
else
|
data/lib/code/object/boolean.rb
CHANGED
|
@@ -3,6 +3,66 @@
|
|
|
3
3
|
class Code
|
|
4
4
|
class Object
|
|
5
5
|
class Boolean < ::Code::Object
|
|
6
|
+
CLASS_DOCUMENTATION = {
|
|
7
|
+
name: "Boolean",
|
|
8
|
+
description: "represents true or false.",
|
|
9
|
+
examples: [
|
|
10
|
+
"Boolean",
|
|
11
|
+
"Boolean.new(true)",
|
|
12
|
+
"Boolean.new(false)"
|
|
13
|
+
]
|
|
14
|
+
}.freeze
|
|
15
|
+
INSTANCE_FUNCTIONS = {
|
|
16
|
+
"&" => {
|
|
17
|
+
name: "&",
|
|
18
|
+
description: "returns true when both booleans are true.",
|
|
19
|
+
examples: ["true & true", "true & false", "false & false"]
|
|
20
|
+
},
|
|
21
|
+
"bitwise_and" => {
|
|
22
|
+
name: "bitwise_and",
|
|
23
|
+
description: "returns true when both booleans are true.",
|
|
24
|
+
examples: [
|
|
25
|
+
"true.bitwise_and(true)",
|
|
26
|
+
"true.bitwise_and(false)",
|
|
27
|
+
"false.bitwise_and(false)"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"|" => {
|
|
31
|
+
name: "|",
|
|
32
|
+
description: "returns true when either boolean is true.",
|
|
33
|
+
examples: ["true | false", "false | true", "false | false"]
|
|
34
|
+
},
|
|
35
|
+
"bitwise_or" => {
|
|
36
|
+
name: "bitwise_or",
|
|
37
|
+
description: "returns true when either boolean is true.",
|
|
38
|
+
examples: [
|
|
39
|
+
"true.bitwise_or(false)",
|
|
40
|
+
"false.bitwise_or(true)",
|
|
41
|
+
"false.bitwise_or(false)"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"^" => {
|
|
45
|
+
name: "^",
|
|
46
|
+
description: "returns true when exactly one boolean is true.",
|
|
47
|
+
examples: ["true ^ false", "true ^ true", "false ^ false"]
|
|
48
|
+
},
|
|
49
|
+
"bitwise_xor" => {
|
|
50
|
+
name: "bitwise_xor",
|
|
51
|
+
description: "returns true when exactly one boolean is true.",
|
|
52
|
+
examples: [
|
|
53
|
+
"true.bitwise_xor(false)",
|
|
54
|
+
"true.bitwise_xor(true)",
|
|
55
|
+
"false.bitwise_xor(false)"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
}.freeze
|
|
59
|
+
|
|
60
|
+
def self.function_documentation(scope)
|
|
61
|
+
return INSTANCE_FUNCTIONS if scope == :instance
|
|
62
|
+
|
|
63
|
+
{}
|
|
64
|
+
end
|
|
65
|
+
|
|
6
66
|
def initialize(*args, **_kargs, &_block)
|
|
7
67
|
self.raw =
|
|
8
68
|
(args.first.is_an?(Object) ? args.first.truthy? : !!args.first)
|