-
Notifications
You must be signed in to change notification settings - Fork 8
/
integer.ex
127 lines (103 loc) · 3.25 KB
/
integer.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
defmodule RDF.XSD.Integer do
@moduledoc """
`RDF.XSD.Datatype` for XSD integers.
Although the XSD spec defines integers as derived from `xsd:decimal` we implement
it here as a primitive datatype for simplicity and performance reasons.
"""
@type valid_value :: integer
use RDF.XSD.Datatype.Primitive,
name: "integer",
id: RDF.Utils.Bootstrapping.xsd_iri("integer")
alias RDF.XSD
def_applicable_facet XSD.Facets.MinInclusive
def_applicable_facet XSD.Facets.MaxInclusive
def_applicable_facet XSD.Facets.MinExclusive
def_applicable_facet XSD.Facets.MaxExclusive
def_applicable_facet XSD.Facets.TotalDigits
def_applicable_facet XSD.Facets.Pattern
@doc false
def min_inclusive_conform?(min_inclusive, value, _lexical) do
value >= min_inclusive
end
@doc false
def max_inclusive_conform?(max_inclusive, value, _lexical) do
value <= max_inclusive
end
@doc false
def min_exclusive_conform?(min_exclusive, value, _lexical) do
value > min_exclusive
end
@doc false
def max_exclusive_conform?(max_exclusive, value, _lexical) do
value < max_exclusive
end
@doc false
def total_digits_conform?(total_digits, value, _lexical) do
digit_count(value) <= total_digits
end
@doc false
def pattern_conform?(pattern, _value, lexical) do
XSD.Facets.Pattern.conform?(pattern, lexical)
end
@impl XSD.Datatype
def lexical_mapping(lexical, _) do
case Integer.parse(lexical) do
{integer, ""} -> integer
{_, _} -> @invalid_value
:error -> @invalid_value
end
end
@impl XSD.Datatype
@spec elixir_mapping(valid_value | any, Keyword.t()) :: value
def elixir_mapping(value, _)
def elixir_mapping(value, _) when is_integer(value), do: value
def elixir_mapping(_, _), do: @invalid_value
@impl RDF.Literal.Datatype
def do_cast(value)
def do_cast(%XSD.String{} = xsd_string) do
xsd_string.value |> new() |> canonical()
end
def do_cast(literal) do
cond do
XSD.Boolean.datatype?(literal) ->
case literal.value do
false -> new(0)
true -> new(1)
end
XSD.Decimal.datatype?(literal) ->
literal.value
|> Decimal.round(0, :down)
|> Decimal.to_integer()
|> new()
# we're catching the XSD.Floats with this too
is_float(literal.value) and XSD.Double.datatype?(literal) ->
literal.value
|> trunc()
|> new()
true ->
super(literal)
end
end
@impl RDF.Literal.Datatype
def do_equal_value_same_or_derived_datatypes?(left, right),
do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def do_equal_value_different_datatypes?(left, right),
do: XSD.Numeric.do_equal_value?(left, right)
@impl RDF.Literal.Datatype
def do_compare(left, right), do: XSD.Numeric.do_compare(left, right)
@doc """
The number of digits in the XML Schema canonical form of the literal value.
"""
@spec digit_count(RDF.Literal.t() | integer) :: non_neg_integer | nil
def digit_count(%datatype{} = literal) do
if datatype?(literal) and datatype.valid?(literal) do
literal
|> datatype.value()
|> digit_count()
end
end
def digit_count(integer) when is_integer(integer) do
integer |> Integer.digits() |> length()
end
end