scratch_test_model/scopes/
block_wrapper.rs1use crate::{
2 Id,
3 aux::{JsonBlocks, JsonCtx, WithJsonContextExt},
4 blocks::BlockKind,
5 error::BlockError,
6};
7
8#[derive(Debug, derive_getters::Getters, PartialEq)]
19pub struct BlockWrapper {
20 id: Id,
22 inner: BlockKind,
24 next: Option<Id>,
26 parent: Option<Id>,
33 shadow: bool,
35 top_level_pos: Option<Position>,
42}
43
44#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, derive_getters::Getters)]
45pub struct Position {
46 x: i64,
47 y: i64,
48}
49
50impl BlockWrapper {
51 pub(crate) fn from_json<'a>(
52 all_blocks: JsonBlocks<'a>,
53 id: Id,
54 obj: &'a serde_json::Value,
55 ) -> Result<Self, JsonCtx<'a, BlockError<'a>>> {
56 let next = read_maybe_string(obj, "next").with_ctx(obj)?.map(Id::from);
57 let parent = read_maybe_string(obj, "parent")
58 .with_ctx(obj)?
59 .map(Id::from);
60 let shadow = read_bool(obj, "shadow").with_ctx(obj)?;
61
62 let top_level_pos = {
63 let top_level = read_bool(obj, "topLevel").with_ctx(obj)?;
64 if top_level {
65 let x = read_i64(obj, "x").with_ctx(obj)?;
66 let y = read_i64(obj, "y").with_ctx(obj)?;
67 Some(Position { x, y })
68 } else {
69 None
70 }
71 };
72
73 let inner =
74 BlockKind::from_json(all_blocks, &id).map_err(|ctx| ctx.map_err(BlockError::Kind))?;
75
76 Ok(Self {
77 id,
78 inner,
79 next,
80 parent,
81 shadow,
82 top_level_pos,
83 })
84 }
85}
86
87fn read_maybe_string<'a>(
88 obj: &'a serde_json::Value,
89 key: &'static str,
90) -> Result<Option<&'a str>, BlockError<'a>> {
91 Ok(obj
92 .get(key)
93 .ok_or(BlockError::MissingMandatoryAttr(key))?
94 .as_str())
95}
96
97fn read_bool<'a>(obj: &serde_json::Value, key: &'static str) -> Result<bool, BlockError<'a>> {
98 obj.get(key)
99 .ok_or(BlockError::MissingMandatoryAttr(key))?
100 .as_bool()
101 .ok_or(BlockError::AttrType {
102 attr_name: key,
103 expected_type: "bool",
104 })
105}
106
107fn read_i64<'a>(obj: &'a serde_json::Value, key: &'static str) -> Result<i64, BlockError<'a>> {
108 obj.get(key)
109 .ok_or(BlockError::MissingMandatoryAttr(key))?
110 .as_i64()
111 .ok_or(BlockError::AttrType {
112 attr_name: key,
113 expected_type: "i64",
114 })
115}