Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lucacorti committed Sep 24, 2024
1 parent 208fbd8 commit 0938752
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 14 deletions.
29 changes: 23 additions & 6 deletions lib/sassone/builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ defimpl Sassone.Builder, for: Any do
%Field{struct(Field, field_options) | xml_name: xml_name, name: name}
end)

{elements, attributes} =
{attributes, elements} =
Enum.split_with(fields, fn %Field{} = field ->
field.type == :element
field.type == :attribute
end)

start_document = generate_start_document(module)
end_document = generate_end_document()
start_element = generate_start_element(elements)
start_element = generate_start_element(elements, attributes)
characters = generate_characters(elements)
end_element = generate_end_element(elements)

Expand Down Expand Up @@ -163,13 +163,30 @@ defimpl Sassone.Builder, for: Any do
end
end

defp generate_start_element(elements) do
Enum.filter(elements, fn %Field{} = field -> field.parse end)
defp generate_start_element(elements, attributes) do
Enum.filter(elements, fn %Field{} = field -> field.parse and field.type != :content end)
|> Enum.reduce(
[
quote do
@impl Sassone.Handler
def handle_event(:start_element, _data, state), do: {:ok, state}
def handle_event(:start_element, {ns, element, attributes}, %Parser{} = parser) do
state =
unquote(
Enum.map(attributes, fn %Field{} = field -> {field.name, field.xml_name} end)
)
|> Enum.reduce(parser.state, fn {key, xml_name}, state ->
value =
Enum.find_value(attributes, fn {_ns, name, value} ->
if name == xml_name, do: value
end)

unless is_nil(value) do
put_in(state, Enum.reverse([key | parser.keys]), value)
end
end)

{:ok, %Parser{parser | state: state}}
end
end
],
fn
Expand Down
12 changes: 4 additions & 8 deletions lib/sassone/builder/field.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@ defmodule Sassone.Builder.Field do
A struct representing the builder options for a struct field.
"""

@type type :: :element | :attribute

@type name :: atom()

@type t :: %__MODULE__{
name: name(),
name: atom(),
parse: boolean(),
many: boolean(),
struct: module(),
build: boolean(),
type: type(),
type: :attribute | :content | :element,
xml_name: String.t()
}

@enforce_keys [:name, :parse, :build, :type, :xml_name]
@enforce_keys [:name, :type, :xml_name]
defstruct build: true,
name: nil,
many: false,
Expand Down Expand Up @@ -66,7 +62,7 @@ defmodule Sassone.Builder.Field do
],
type: [
doc: "How the field is represented in XML: `:element`, `:attribute`, `:content`.",
type: {:in, [:element, :attribute]},
type: {:in, [:attribute, :content, :element]},
default: :element
]
]
Expand Down
4 changes: 4 additions & 0 deletions lib/sassone/xml.ex
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ defmodule Sassone.XML do
Enum.reduce(values, elements, &build_element(field, &1, &2))
end

defp build_element(%Field{type: :content}, value, elements) do
[characters(value) | elements]
end

defp build_element(%Field{} = field, value, elements) do
if Builder.impl_for(value) do
[build(value, field.xml_name) | elements]
Expand Down
20 changes: 20 additions & 0 deletions test/sassone/builder_test.exs
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
defmodule Sassone.BuilderTest do
use ExUnit.Case, async: true

alias Sassone.Builder
alias Sassone.TestSchemas.Person

describe "building" do
test "encode simple schema" do
assert ~s|<person gender="female">Alice</person>| =
Builder.build(%Person{gender: "female", name: "Alice"})
|> Sassone.encode!()
end

test "decode simple schema" do

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.12.x/24.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.13.x/24.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.14.x/24.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.15.x/24.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.16.x/24.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.14.x/25.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.15.x/25.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.16.x/25.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.17.x/25.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.14.x/26.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.15.x/26.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.16.x/26.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.17.x/26.x)

test building decode simple schema (Sassone.BuilderTest)

Check failure on line 14 in test/sassone/builder_test.exs

View workflow job for this annotation

GitHub Actions / Test (1.17.x/27.x)

test building decode simple schema (Sassone.BuilderTest)
assert {:ok, {Person, %{gender: "female", name: "Alice"}}} =
Sassone.parse_string(
~s|<person gender="female">Alice</person>|,
Builder.handler(%Person{}),
nil
)
end
end
end
14 changes: 14 additions & 0 deletions test/support/test_schemas.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule Sassone.TestSchemas do
@moduledoc false

defmodule Person do
@derive {
Sassone.Builder,
case: :snake,
debug: true,
root_element: "person",
fields: [gender: [type: :attribute], name: [type: :content]]
}
defstruct [:gender, :name]
end
end

0 comments on commit 0938752

Please sign in to comment.