Merge pull request #9 from pukkamustard/base64Binary

Add XSD.Base64Binary
This commit is contained in:
Marcel Otto 2020-12-06 20:36:21 +01:00 committed by GitHub
commit be87736e60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 131 additions and 3 deletions

View file

@ -36,7 +36,8 @@ defmodule RDF.Literal.Datatype.Registry do
XSD.Date,
XSD.Time,
XSD.DateTime,
XSD.AnyURI
XSD.AnyURI,
XSD.Base64Binary
] ++ @builtin_numeric_datatypes
@builtin_datatypes [RDF.LangString | @builtin_xsd_datatypes]

View file

@ -52,7 +52,7 @@ defmodule RDF.XSD.Datatype do
| `xsd:gMonthDay` | |
| `xsd:gDay` | |
| `xsd:gMonth` | |
| `xsd:base64Binary` | |
| `xsd:base64Binary` | `RDF.XSD.Base64Binary` |
| `xsd:hexBinary` | |
| `xsd:anyURI` | `RDF.XSD.AnyURI` |
| `xsd:QName` | |

View file

@ -0,0 +1,64 @@
defmodule RDF.XSD.Base64Binary do
@moduledoc """
`RDF.XSD.Datatype` for XSD base64Binary.
"""
@type valid_value :: binary()
use RDF.XSD.Datatype.Primitive,
name: "base64Binary",
id: RDF.Utils.Bootstrapping.xsd_iri("base64Binary")
alias RDF.XSD
def_applicable_facet XSD.Facets.MinLength
def_applicable_facet XSD.Facets.MaxLength
def_applicable_facet XSD.Facets.Length
def_applicable_facet XSD.Facets.Pattern
@doc false
def min_length_conform?(min_length, value, _lexical) do
byte_size(value) >= min_length
end
@doc false
def max_length_conform?(max_length, value, _lexical) do
byte_size(value) <= max_length
end
@doc false
def length_conform?(length, value, _lexical) do
byte_size(value) == length
end
@doc false
def pattern_conform?(pattern, value, _lexical) do
XSD.Facets.Pattern.conform?(pattern, value)
end
@impl XSD.Datatype
@spec lexical_mapping(String.t(), Keyword.t()) :: valid_value()
def lexical_mapping(lexical, _) do
case Base.decode64(lexical) do
{:ok, value} ->
value
_ ->
@invalid_value
end
end
@impl XSD.Datatype
@spec elixir_mapping(any, Keyword.t()) :: nil | valid_value()
def elixir_mapping(value, _) when is_binary(value), do: value
def elixir_mapping(_, _), do: @invalid_value
@impl XSD.Datatype
@spec canonical_mapping(valid_value()) :: String.t()
def canonical_mapping(value), do: Base.encode64(value)
@impl RDF.Literal.Datatype
def do_cast(value)
def do_cast(%XSD.String{} = xsd_string), do: new(xsd_string.value, as_value: true)
def do_cast(literal), do: super(literal)
end

View file

@ -24,7 +24,6 @@ defmodule RDF.Literal.Datatype.RegistryTest do
ENTITY
yearMonthDuration
IDREFS
base64Binary
token
NCName
NMTOKEN

View file

@ -0,0 +1,64 @@
defmodule RDF.XSD.Base64BinaryTest do
use RDF.XSD.Datatype.Test.Case,
datatype: RDF.XSD.Base64Binary,
name: "base64Binary",
primitive: true,
applicable_facets: [
RDF.XSD.Facets.MinLength,
RDF.XSD.Facets.MaxLength,
RDF.XSD.Facets.Length,
RDF.XSD.Facets.Pattern
],
facets: %{
max_length: nil,
min_length: nil,
length: nil,
pattern: nil
},
valid: %{
# input => { value, lexical, canonicalized }
# "foo" does not require any padding
Base.encode64("foo") => {"foo", nil, Base.encode64("foo")},
# "foob" does require padding
Base.encode64("foob") => {"foob", nil, Base.encode64("foob")},
Base.encode64(<<0::32>>) => {<<0::32>>, nil, Base.encode64(<<0::32>>)}
},
invalid: [
"not a base64 encoded value",
Base.encode64("foob", padding: false),
0,
42,
3.14,
true,
false
]
describe "new/2" do
test "interpret string as value" do
assert XSD.base64Binary("foo", as_value: true) == XSD.base64Binary(Base.encode64("foo"))
end
test "interpret string as value even if string is correctly encodded Base64" do
assert XSD.base64Binary(Base.encode64("foo"), as_value: true) ==
XSD.base64Binary(Base.encode64(Base.encode64("foo")))
end
end
describe "cast/1" do
test "casting a base64Binary returns the input as is" do
assert XSD.base64Binary("foo", as_value: true) |> XSD.Base64Binary.cast() ==
XSD.base64Binary("foo", as_value: true)
end
test "casting a string" do
assert XSD.string("foo") |> XSD.Base64Binary.cast() ==
XSD.base64Binary("foo", as_value: true)
end
test "string value is interpret as value (even if valid Base64 encoded string)" do
assert XSD.string(Base.encode64("Hello World!"))
|> XSD.Base64Binary.cast() !==
XSD.base64Binary("Hello World!", as_value: true)
end
end
end