├── .gitignore
├── .travis.yml
├── Cargo.toml
├── README.md
├── rsx-arena
├── Cargo.toml
└── src
│ ├── common.rs
│ ├── hashmap
│ ├── arena.rs
│ ├── bucket.rs
│ └── mod.rs
│ ├── lib.rs
│ ├── util.rs
│ └── vec
│ ├── arena.rs
│ └── mod.rs
├── rsx-dom
├── Cargo.toml
├── src
│ ├── convert.rs
│ ├── export.rs
│ ├── graph
│ │ ├── mod.rs
│ │ ├── node_id.rs
│ │ ├── node_ref.rs
│ │ ├── node_ref_mut.rs
│ │ ├── node_ref_mut_pair.rs
│ │ └── tree.rs
│ ├── lib.rs
│ ├── macros.rs
│ ├── types.rs
│ └── util.rs
└── tests
│ ├── spec_quote.rs
│ └── spec_runtime.rs
├── rsx-tree
├── Cargo.toml
└── src
│ ├── iter.rs
│ ├── lib.rs
│ ├── node.rs
│ ├── node_id.rs
│ ├── node_ref.rs
│ ├── node_ref_mut.rs
│ ├── node_ref_mut_pair.rs
│ └── tree.rs
├── rust-toolchain
└── rustfmt.toml
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | Cargo.lock
3 | **/*.rs.bk
4 | .vscode
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: rust
2 | os:
3 | - linux
4 | # - osx
5 | rust:
6 | - nightly
7 | notifications:
8 | email: false
9 | before_script:
10 | - cargo +nightly install rustfmt-nightly --vers 0.3.8 --force
11 | - cargo +nightly install clippy --force
12 | - export PATH=$PATH:~/.cargo/bin
13 | script:
14 | - cargo build --verbose
15 | - cargo test --verbose
16 | - cargo +nightly fmt --all -- --write-mode=diff
17 | - cargo +nightly clippy --all -- --deny warnings
18 | after_success:
19 | - |
20 | if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" ]]; then
21 | cargo doc &&
22 | echo "" > target/doc/index.html &&
23 | git clone https://github.com/davisp/ghp-import.git &&
24 | ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc &&
25 | echo "Uploaded documentation"
26 | fi
27 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "rsx-arena",
4 | "rsx-tree",
5 | "rsx-dom"
6 | ]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **Under heavy research and development, please don't use this yet!**
2 |
3 | # rsx-dom
4 | [](https://opensource.org/licenses/MPL-2.0)
5 | [](https://travis-ci.org/victorporof/rsx-dom)
6 |
7 | Simple node tree abstraction layer over RSX syntax trees
8 |
9 | ## Purpose
10 | A backwards compatible higher level of abstraction over the AST generated by the [RSX parser](https://github.com/victorporof/rsx-parser). Since working directly with `rsx_parser::RSXElement` abstract syntax trees (or Rust's [proc_macro::TokenStream](https://doc.rust-lang.org/proc_macro/struct.TokenStream.html)) can be tedious, and the underlying parser and compiler data formats can change at any time, a simpler DOM structure is useful as an abstraction layer in the scope of writing [RSX code](https://github.com/victorporof/rsx-compiler-plugin).
11 |
12 | ## How to use
13 | [Documentation](https://victorporof.github.io/rsx-dom)
14 |
15 | This crate concerns itself strictly generating a DOM node tree from a RSX syntax tree. If you're just looking to write RSX in your project, take a look at the [RSX compiler plugin](https://github.com/victorporof/rsx_compiler_plugin) instead.
16 |
17 | Otherwise, add this to your `Cargo.toml` file:
18 |
19 | ```toml
20 | [dependencies]
21 | rsx-dom = { git = "https://github.com/victorporof/rsx-dom.git" }
22 | ```
23 |
24 | RSX parsing is enabled via the `rsx-parse` feature gate.
25 |
26 | ```toml
27 | [dependencies]
28 | rsx-dom = { git = "https://github.com/victorporof/rsx-dom.git", features = ["rsx-parse"] }
29 | ```
30 |
31 | When used as part of the [RSX compiler plugin](https://github.com/victorporof/rsx_compiler_plugin), the convertion is automatic between `rsx_parser::RSXElement` abstract syntax trees to the more convenient `rsx_dom::DOMNode` elements, because the AST is directly tokenized into a DOM tree to avoid any runtime work! Templating is thus a zero cost abstraction.
32 |
33 | If manual instantiation is desired, simply import the library into your code to build `rsx_dom::DOMNode` elements.
34 |
35 | ```rust
36 | extern crate rsx_dom;
37 | use rsx_dom::types::DOMNode;
38 |
39 | let node = DOMNode::from(...);
40 | ```
41 |
42 | Note that when used as a compiler plugin,
43 |
44 | *Note: `rsx-dom` also re-exports the `rsx-parser` [crate](https://github.com/victorporof/rsx-parser), only needed if you need to parse character streams (such as strings) directly. You'll probably prefer using the `rsx!` macro as part of the [RSX compiler plugin](https://github.com/victorporof/rsx_compiler_plugin) instead.*
45 |
46 | See all the available [types](https://github.com/victorporof/rsx-parser/blob/master/src/parse_elements_types.rs) for more details.
47 |
--------------------------------------------------------------------------------
/rsx-arena/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rsx-arena"
3 | version = "0.1.0"
4 | authors = ["Victor Porof "]
5 |
6 | [lib]
7 | name = "rsx_arena"
8 |
9 | [dependencies]
10 | fnv = "1.0.6"
11 | num-traits = "0.2.0"
12 | smallvec = "0.6.0"
13 |
--------------------------------------------------------------------------------
/rsx-arena/src/common.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::fmt;
13 | use std::hash::{Hash, Hasher};
14 | use std::marker::PhantomData;
15 | use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
16 |
17 | use num_traits::{FromPrimitive, ToPrimitive};
18 |
19 | #[derive(PartialOrd, Ord)]
20 | pub(crate) struct BucketId(u32, PhantomData);
21 |
22 | impl fmt::Debug for BucketId {
23 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
24 | write!(f, "BucketId({})", self.0)
25 | }
26 | }
27 |
28 | impl Eq for BucketId {}
29 |
30 | impl PartialEq for BucketId {
31 | fn eq(&self, other: &Self) -> bool {
32 | self.0 == other.0
33 | }
34 | }
35 |
36 | impl Copy for BucketId {}
37 |
38 | impl Clone for BucketId {
39 | fn clone(&self) -> BucketId {
40 | *self
41 | }
42 | }
43 |
44 | impl Hash for BucketId {
45 | fn hash(&self, hasher: &mut H) {
46 | self.0.hash(hasher);
47 | }
48 | }
49 |
50 | impl BucketId {
51 | pub(crate) fn new(value: u32) -> Self {
52 | BucketId(value, PhantomData)
53 | }
54 |
55 | pub(crate) fn generate() -> Self {
56 | static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
57 | BucketId::new(NEXT_ID.fetch_add(1, Ordering::Relaxed) as u32)
58 | }
59 | }
60 |
61 | #[derive(PartialOrd, Ord)]
62 | pub(crate) struct EntryId(u32, PhantomData);
63 |
64 | impl fmt::Debug for EntryId {
65 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
66 | write!(f, "EntryId({})", self.0)
67 | }
68 | }
69 |
70 | impl Eq for EntryId {}
71 |
72 | impl PartialEq for EntryId {
73 | fn eq(&self, other: &Self) -> bool {
74 | self.0 == other.0
75 | }
76 | }
77 |
78 | impl Copy for EntryId {}
79 |
80 | impl Clone for EntryId {
81 | fn clone(&self) -> EntryId {
82 | *self
83 | }
84 | }
85 |
86 | impl Hash for EntryId {
87 | fn hash(&self, hasher: &mut H) {
88 | self.0.hash(hasher);
89 | }
90 | }
91 |
92 | impl EntryId {
93 | pub(crate) fn new(value: u32) -> Self {
94 | EntryId(value, PhantomData)
95 | }
96 |
97 | pub(crate) fn generate(&mut self) -> Self {
98 | let index = self.0;
99 | self.0 += 1;
100 | EntryId::new(index)
101 | }
102 |
103 | pub(crate) fn to_index(&self) -> usize {
104 | self.0 as usize
105 | }
106 | }
107 |
108 | #[derive(PartialOrd, Ord)]
109 | pub struct ArenaItemId {
110 | pub(crate) bucket_id: BucketId,
111 | pub(crate) entry_id: EntryId
112 | }
113 |
114 | impl fmt::Debug for ArenaItemId {
115 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
116 | write!(f, "ArenaItemId({:?}, {:?})", self.bucket_id, self.entry_id)
117 | }
118 | }
119 |
120 | impl Eq for ArenaItemId {}
121 |
122 | impl PartialEq for ArenaItemId {
123 | fn eq(&self, other: &Self) -> bool {
124 | self.bucket_id == other.bucket_id && self.entry_id == other.entry_id
125 | }
126 | }
127 |
128 | impl Copy for ArenaItemId {}
129 |
130 | impl Clone for ArenaItemId {
131 | fn clone(&self) -> ArenaItemId {
132 | *self
133 | }
134 | }
135 |
136 | impl Hash for ArenaItemId {
137 | fn hash(&self, hasher: &mut H) {
138 | self.bucket_id.hash(hasher);
139 | self.entry_id.hash(hasher);
140 | }
141 | }
142 |
143 | impl ToPrimitive for ArenaItemId {
144 | fn to_i64(&self) -> Option {
145 | None
146 | }
147 |
148 | fn to_u64(&self) -> Option {
149 | let bucket_id = u64::from(self.bucket_id.0);
150 | let entry_id = u64::from(self.entry_id.0);
151 | Some(bucket_id << 32 | entry_id)
152 | }
153 | }
154 |
155 | impl FromPrimitive for ArenaItemId {
156 | fn from_i64(_: i64) -> Option {
157 | None
158 | }
159 |
160 | fn from_u64(value: u64) -> Option {
161 | let bucket_id = BucketId::new(((value >> 32) & 0xffff_ffff) as u32);
162 | let entry_id = EntryId::new((value & 0xffff_ffff) as u32);
163 | Some(ArenaItemId {
164 | bucket_id,
165 | entry_id
166 | })
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/rsx-arena/src/hashmap/arena.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::ops::AddAssign;
13 |
14 | use smallvec::SmallVec;
15 |
16 | use hashmap::bucket::HashmapBucket;
17 | use types::ArenaItemId;
18 | use util::as_mut;
19 |
20 | #[derive(Debug, PartialEq)]
21 | pub struct HashmapArena {
22 | buckets: SmallVec<[HashmapBucket; 1]>
23 | }
24 |
25 | impl Default for HashmapArena {
26 | fn default() -> Self {
27 | HashmapArena {
28 | buckets: SmallVec::from_buf([HashmapBucket::new()])
29 | }
30 | }
31 | }
32 |
33 | impl HashmapArena {
34 | pub fn new() -> Self {
35 | HashmapArena::default()
36 | }
37 |
38 | pub fn alloc(&mut self, value: T) -> ArenaItemId {
39 | self.buckets[0].alloc(value)
40 | }
41 |
42 | pub fn dealloc(&mut self, id: ArenaItemId) -> Option {
43 | self.buckets.iter_mut().find(|v| v.owns(id))?.dealloc(id)
44 | }
45 |
46 | #[inline]
47 | pub fn get(&self, id: ArenaItemId) -> Option<&T> {
48 | self.buckets.iter().find(|v| v.owns(id))?.get(id)
49 | }
50 |
51 | #[inline]
52 | pub fn get_mut(&mut self, id: ArenaItemId) -> Option<&mut T> {
53 | self.buckets.iter_mut().find(|v| v.owns(id))?.get_mut(id)
54 | }
55 |
56 | #[inline]
57 | pub unsafe fn get_as_mut<'a>(&mut self, id: ArenaItemId) -> Option<&'a mut T> {
58 | as_mut(self.get_mut(id))
59 | }
60 |
61 | #[inline]
62 | pub fn get_mut_pair(&mut self, first_id: ArenaItemId, second_id: ArenaItemId) -> (Option<&mut T>, Option<&mut T>) {
63 | assert_ne!(first_id, second_id);
64 | let first = unsafe { self.get_as_mut(first_id) };
65 | let second = unsafe { self.get_as_mut(second_id) };
66 | (first, second)
67 | }
68 | }
69 |
70 | impl AddAssign for HashmapArena {
71 | fn add_assign(&mut self, rhs: Self) {
72 | self.buckets.extend(rhs.buckets)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/rsx-arena/src/hashmap/bucket.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use fnv::FnvHashMap;
13 |
14 | use types::{ArenaItemId, BucketId, EntryId};
15 | use util::as_mut;
16 |
17 | #[derive(Debug)]
18 | pub struct HashmapBucket {
19 | bucket_id: BucketId,
20 | next_entry_id: EntryId,
21 | map: FnvHashMap, T>
22 | }
23 |
24 | impl PartialEq for HashmapBucket {
25 | fn eq(&self, other: &Self) -> bool {
26 | self.bucket_id == other.bucket_id
27 | }
28 | }
29 |
30 | impl Default for HashmapBucket {
31 | fn default() -> Self {
32 | HashmapBucket {
33 | bucket_id: BucketId::generate(),
34 | next_entry_id: EntryId::new(0),
35 | map: FnvHashMap::default()
36 | }
37 | }
38 | }
39 |
40 | impl HashmapBucket {
41 | pub fn new() -> Self {
42 | HashmapBucket::default()
43 | }
44 |
45 | pub fn owns(&self, id: ArenaItemId) -> bool {
46 | self.bucket_id == id.bucket_id
47 | }
48 |
49 | pub fn alloc(&mut self, value: T) -> ArenaItemId {
50 | let item_id = ArenaItemId {
51 | bucket_id: self.bucket_id,
52 | entry_id: self.next_entry_id.generate()
53 | };
54 | self.map.insert(item_id, value);
55 | item_id
56 | }
57 |
58 | pub fn dealloc(&mut self, id: ArenaItemId) -> Option {
59 | debug_assert_eq!(self.bucket_id, id.bucket_id);
60 | self.map.remove(&id)
61 | }
62 |
63 | #[inline]
64 | pub fn get(&self, id: ArenaItemId) -> Option<&T> {
65 | debug_assert_eq!(self.bucket_id, id.bucket_id);
66 | self.map.get(&id)
67 | }
68 |
69 | #[inline]
70 | pub fn get_mut(&mut self, id: ArenaItemId) -> Option<&mut T> {
71 | debug_assert_eq!(self.bucket_id, id.bucket_id);
72 | self.map.get_mut(&id)
73 | }
74 |
75 | #[inline]
76 | pub unsafe fn get_as_mut<'a>(&mut self, id: ArenaItemId) -> Option<&'a mut T> {
77 | as_mut(self.get_mut(id))
78 | }
79 |
80 | #[inline]
81 | pub fn get_mut_pair(&mut self, first_id: ArenaItemId, second_id: ArenaItemId) -> (Option<&mut T>, Option<&mut T>) {
82 | assert_ne!(first_id, second_id);
83 | let first = unsafe { self.get_as_mut(first_id) };
84 | let second = unsafe { self.get_as_mut(second_id) };
85 | (first, second)
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/rsx-arena/src/hashmap/mod.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | mod arena;
13 | mod bucket;
14 |
15 | pub use self::arena::*;
16 | pub use self::bucket::*;
17 |
--------------------------------------------------------------------------------
/rsx-arena/src/lib.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | extern crate fnv;
13 | extern crate num_traits;
14 | extern crate smallvec;
15 |
16 | mod util;
17 | mod common;
18 | mod hashmap;
19 | mod vec;
20 |
21 | pub mod types {
22 | pub use common::*;
23 | pub use hashmap::*;
24 | pub use vec::*;
25 | }
26 |
--------------------------------------------------------------------------------
/rsx-arena/src/util.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | #[inline]
13 | pub unsafe fn as_mut<'a, V>(value: Option<&mut V>) -> Option<&'a mut V> {
14 | value.map(|v| v as *mut V).map(|v| &mut *v)
15 | }
16 |
--------------------------------------------------------------------------------
/rsx-arena/src/vec/arena.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::ops::AddAssign;
13 |
14 | use types::{ArenaItemId, BucketId, EntryId};
15 | use util::as_mut;
16 |
17 | #[derive(Debug)]
18 | pub struct VecArena {
19 | bucket_id: BucketId,
20 | vec: Vec
21 | }
22 |
23 | impl PartialEq for VecArena {
24 | fn eq(&self, other: &Self) -> bool {
25 | self.bucket_id == other.bucket_id
26 | }
27 | }
28 |
29 | impl Default for VecArena {
30 | fn default() -> Self {
31 | VecArena {
32 | bucket_id: BucketId::generate(),
33 | vec: Vec::with_capacity(1024)
34 | }
35 | }
36 | }
37 |
38 | impl VecArena {
39 | pub fn new() -> Self {
40 | VecArena::default()
41 | }
42 |
43 | pub fn owns(&self, id: ArenaItemId) -> bool {
44 | self.bucket_id == id.bucket_id
45 | }
46 |
47 | pub fn alloc(&mut self, value: T) -> ArenaItemId {
48 | let item_id = ArenaItemId {
49 | bucket_id: self.bucket_id,
50 | entry_id: EntryId::new(self.vec.len() as u32)
51 | };
52 | self.vec.push(value);
53 | item_id
54 | }
55 |
56 | pub fn dealloc(&mut self, _: ArenaItemId) -> Option {
57 | unimplemented!()
58 | }
59 |
60 | #[inline]
61 | pub fn get(&self, id: ArenaItemId) -> Option<&T> {
62 | debug_assert_eq!(self.bucket_id, id.bucket_id);
63 | Some(unsafe { self.vec.get_unchecked(id.entry_id.to_index()) })
64 | }
65 |
66 | #[inline]
67 | pub fn get_mut(&mut self, id: ArenaItemId) -> Option<&mut T> {
68 | debug_assert_eq!(self.bucket_id, id.bucket_id);
69 | Some(unsafe { self.vec.get_unchecked_mut(id.entry_id.to_index()) })
70 | }
71 |
72 | #[inline]
73 | pub unsafe fn get_as_mut<'a>(&mut self, id: ArenaItemId) -> Option<&'a mut T> {
74 | as_mut(self.get_mut(id))
75 | }
76 |
77 | #[inline]
78 | pub fn get_mut_pair(&mut self, first_id: ArenaItemId, second_id: ArenaItemId) -> (Option<&mut T>, Option<&mut T>) {
79 | assert_ne!(first_id, second_id);
80 | let first = unsafe { self.get_as_mut(first_id) };
81 | let second = unsafe { self.get_as_mut(second_id) };
82 | (first, second)
83 | }
84 | }
85 |
86 | impl AddAssign for VecArena {
87 | fn add_assign(&mut self, _: Self) {
88 | panic!("Extending vec-based arenas is not supported.");
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/rsx-arena/src/vec/mod.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | mod arena;
13 |
14 | pub use self::arena::*;
15 |
--------------------------------------------------------------------------------
/rsx-dom/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "rsx-dom"
3 | version = "0.1.0"
4 | authors = ["Victor Porof "]
5 |
6 | [lib]
7 | name = "rsx_dom"
8 |
9 | [features]
10 | default = ["rsx-parse", "vec-arena"]
11 | rsx-parse = ["rsx-parser"]
12 | vec-arena = ["rsx-tree/vec-arena"]
13 | hashmap-arena = ["rsx-tree/hashmap-arena"]
14 |
15 | [dependencies]
16 | fnv = "1.0.6"
17 | rsx-shared = { git = "https://github.com/victorporof/rsx-shared.git", default-features = false }
18 | rsx-tree = { path = "../rsx-tree", default-features = false }
19 | serde = { version = "1.0.27", features = ["rc"] }
20 | serde_derive = "1.0.27"
21 |
22 | # Optional
23 | rsx-parser = { git = "https://github.com/victorporof/rsx-parser.git", default-features = false, optional = true }
24 |
25 | [dev-dependencies]
26 | rsx-shared = { git = "https://github.com/victorporof/rsx-shared.git", default-features = false, features = ["impl-dummy"] }
27 | quote = "0.3.15"
28 | syn = { version = "0.11.11", features = ["full"] }
29 |
--------------------------------------------------------------------------------
/rsx-dom/src/convert.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::borrow::Cow;
13 | use std::rc::Rc;
14 |
15 | use rsx_shared::traits::{TComputedStyles, TGenericEvent, TLayoutNode, TStyleDeclarations};
16 |
17 | use types::{
18 | Closure,
19 | DOMAttribute,
20 | DOMAttributeName,
21 | DOMAttributeValue,
22 | DOMAttributes,
23 | DOMData,
24 | DOMNode,
25 | DOMNormalNode,
26 | DOMTagName,
27 | DOMText,
28 | DOMTextNode,
29 | DOMTree,
30 | EventType,
31 | KnownAttributeName,
32 | KnownElementName,
33 | Prop
34 | };
35 |
36 | impl From<()> for DOMNode
37 | where
38 | E: TGenericEvent,
39 | S: TStyleDeclarations,
40 | C: TComputedStyles,
41 | L: TLayoutNode
42 | {
43 | fn from(_: ()) -> Self {
44 | DOMNode::new(DOMData::Void)
45 | }
46 | }
47 |
48 | impl From<&'static str> for DOMNode
49 | where
50 | E: TGenericEvent,
51 | S: TStyleDeclarations,
52 | C: TComputedStyles,
53 | L: TLayoutNode
54 | {
55 | fn from(text: &'static str) -> Self {
56 | DOMNode::new(DOMData::Text(DOMTextNode {
57 | content: DOMText::from(text)
58 | }))
59 | }
60 | }
61 |
62 | impl From for DOMNode
63 | where
64 | E: TGenericEvent,
65 | S: TStyleDeclarations,
66 | C: TComputedStyles,
67 | L: TLayoutNode
68 | {
69 | fn from(text: String) -> Self {
70 | DOMNode::new(DOMData::Text(DOMTextNode {
71 | content: DOMText::from(text)
72 | }))
73 | }
74 | }
75 |
76 | impl_text_node_from_stringifiable!(bool);
77 | impl_text_node_from_stringifiable!(i8);
78 | impl_text_node_from_stringifiable!(u8);
79 | impl_text_node_from_stringifiable!(i16);
80 | impl_text_node_from_stringifiable!(u16);
81 | impl_text_node_from_stringifiable!(i32);
82 | impl_text_node_from_stringifiable!(u32);
83 | impl_text_node_from_stringifiable!(i64);
84 | impl_text_node_from_stringifiable!(u64);
85 | impl_text_node_from_stringifiable!(f32);
86 | impl_text_node_from_stringifiable!(f64);
87 | impl_text_node_from_stringifiable!(isize);
88 | impl_text_node_from_stringifiable!(usize);
89 | impl_text_node_from_stringifiable!(char);
90 |
91 | impl From for DOMNode
92 | where
93 | E: TGenericEvent,
94 | S: TStyleDeclarations,
95 | C: TComputedStyles,
96 | L: TLayoutNode
97 | {
98 | fn from(tag: DOMTagName) -> Self {
99 | let attributes = vec![];
100 | DOMNode::new(DOMData::Normal(DOMNormalNode { tag, attributes }))
101 | }
102 | }
103 |
104 | impl From<(DOMTagName, DOMAttributes)> for DOMNode
105 | where
106 | E: TGenericEvent,
107 | S: TStyleDeclarations,
108 | C: TComputedStyles,
109 | L: TLayoutNode
110 | {
111 | fn from((tag, attributes): (DOMTagName, DOMAttributes)) -> Self {
112 | DOMNode::new(DOMData::Normal(DOMNormalNode { tag, attributes }))
113 | }
114 | }
115 |
116 | impl From> for DOMNode
117 | where
118 | E: TGenericEvent,
119 | S: TStyleDeclarations,
120 | C: TComputedStyles,
121 | L: TLayoutNode
122 | {
123 | fn from(tree: DOMTree) -> Self {
124 | DOMNode::new(DOMData::ShadowHost(tree))
125 | }
126 | }
127 |
128 | impl From<&'static str> for DOMText {
129 | fn from(value: &'static str) -> Self {
130 | DOMText::Static(Cow::from(value))
131 | }
132 | }
133 |
134 | impl From for DOMText {
135 | fn from(value: String) -> Self {
136 | DOMText::Owned(Rc::new(value))
137 | }
138 | }
139 |
140 | impl From for DOMTagName {
141 | fn from(name: KnownElementName) -> Self {
142 | DOMTagName::KnownName(name)
143 | }
144 | }
145 |
146 | impl From<&'static str> for DOMTagName {
147 | fn from(name: &'static str) -> Self {
148 | DOMTagName::Simple(name)
149 | }
150 | }
151 |
152 | impl From<(&'static str, &'static str)> for DOMTagName {
153 | fn from((namespace, name): (&'static str, &'static str)) -> Self {
154 | DOMTagName::NamedspacedName(namespace, name)
155 | }
156 | }
157 |
158 | impl From<(DOMAttributeName, DOMAttributeValue)> for DOMAttribute {
159 | fn from((name, value): (DOMAttributeName, DOMAttributeValue)) -> Self {
160 | DOMAttribute(name, value)
161 | }
162 | }
163 |
164 | impl From for DOMAttributeName {
165 | fn from(name: KnownAttributeName) -> Self {
166 | DOMAttributeName::KnownName(name)
167 | }
168 | }
169 |
170 | impl From for DOMAttributeName {
171 | fn from(name: EventType) -> Self {
172 | DOMAttributeName::EventType(name)
173 | }
174 | }
175 |
176 | impl From<&'static str> for DOMAttributeName {
177 | fn from(name: &'static str) -> Self {
178 | DOMAttributeName::Simple(name)
179 | }
180 | }
181 |
182 | impl From<(&'static str, &'static str)> for DOMAttributeName {
183 | fn from((namespace, name): (&'static str, &'static str)) -> Self {
184 | DOMAttributeName::NamedspacedName(namespace, name)
185 | }
186 | }
187 |
188 | impl From for DOMAttributeValue {
189 | fn from(value: bool) -> Self {
190 | DOMAttributeValue::Boolean(value)
191 | }
192 | }
193 |
194 | impl From for DOMAttributeValue {
195 | fn from(value: f64) -> Self {
196 | DOMAttributeValue::Number(value)
197 | }
198 | }
199 |
200 | impl_number_attribute_from_countable!(i8);
201 | impl_number_attribute_from_countable!(u8);
202 | impl_number_attribute_from_countable!(i16);
203 | impl_number_attribute_from_countable!(u16);
204 | impl_number_attribute_from_countable!(i32);
205 | impl_number_attribute_from_countable!(u32);
206 | impl_number_attribute_from_countable!(i64);
207 | impl_number_attribute_from_countable!(u64);
208 | impl_number_attribute_from_countable!(f32);
209 | impl_number_attribute_from_countable!(isize);
210 | impl_number_attribute_from_countable!(usize);
211 |
212 | impl From for DOMAttributeValue {
213 | fn from(value: char) -> Self {
214 | DOMAttributeValue::Char(value)
215 | }
216 | }
217 |
218 | impl From<&'static str> for DOMAttributeValue {
219 | fn from(value: &'static str) -> Self {
220 | DOMAttributeValue::Str(DOMText::from(value))
221 | }
222 | }
223 |
224 | impl From for DOMAttributeValue {
225 | fn from(value: String) -> Self {
226 | DOMAttributeValue::Str(DOMText::from(value))
227 | }
228 | }
229 |
230 | impl From for DOMAttributeValue {
231 | fn from(value: DOMText) -> Self {
232 | DOMAttributeValue::Str(value)
233 | }
234 | }
235 |
236 | impl From for DOMAttributeValue
237 | where
238 | E: TGenericEvent,
239 | S: TStyleDeclarations,
240 | C: TComputedStyles,
241 | L: TLayoutNode
242 | {
243 | fn from(value: S) -> Self {
244 | DOMAttributeValue::Styles(value)
245 | }
246 | }
247 |
248 | impl From for DOMAttributeValue {
249 | fn from(value: Prop) -> Self {
250 | DOMAttributeValue::Prop(value)
251 | }
252 | }
253 |
254 | impl From> for DOMAttributeValue {
255 | fn from(value: Closure) -> Self {
256 | DOMAttributeValue::EventListener(value)
257 | }
258 | }
259 |
260 | impl From> for DOMAttributeValue {
261 | fn from(value: DOMNode) -> Self {
262 | DOMAttributeValue::Node(value)
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/rsx-dom/src/export.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::convert::TryInto;
13 |
14 | use rsx_shared::traits::{TComputedStyles, TGenericEvent, TLayoutNode, TStyleDeclarations};
15 |
16 | use types::{DOMData, DOMTagName, KnownElementName};
17 |
18 | impl<'a, E, S, C, L> TryInto for &'a DOMData
19 | where
20 | E: TGenericEvent,
21 | S: TStyleDeclarations,
22 | C: TComputedStyles,
23 | L: TLayoutNode
24 | {
25 | type Error = ();
26 |
27 | fn try_into(self) -> Result {
28 | if let Some(&DOMTagName::KnownName(name)) = self.tag() {
29 | Ok(name)
30 | } else {
31 | Err(())
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/rsx-dom/src/graph/mod.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | mod node_id;
13 | mod node_ref;
14 | mod node_ref_mut;
15 | mod node_ref_mut_pair;
16 | mod tree;
17 |
18 | pub use self::node_id::*;
19 | pub use self::node_ref::*;
20 | pub use self::node_ref_mut::*;
21 | pub use self::node_ref_mut_pair::*;
22 | pub use self::tree::*;
23 |
--------------------------------------------------------------------------------
/rsx-dom/src/graph/node_id.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use rsx_tree::types::Id;
13 |
14 | use types::DOMNode;
15 |
16 | pub type DOMNodeId = Id>;
17 | pub type DOMNodeIdPair = (DOMNodeId, DOMNodeId);
18 |
19 | pub type DOMNodeSiblingIds = (Option>, Option>);
20 | pub type DOMNodeEdgeIds = (Option>, Option>);
21 |
--------------------------------------------------------------------------------
/rsx-dom/src/graph/node_ref.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::ops::Deref;
13 |
14 | use rsx_tree::types::Ref;
15 |
16 | use types::{DOMNode, DOMNodeEdgeIds, DOMNodeId, DOMNodeSiblingIds};
17 |
18 | #[derive(Debug, PartialEq)]
19 | pub struct DOMArenaRef<'a, E: 'a, S: 'a, C: 'a, L: 'a> {
20 | raw: Ref<'a, DOMNode>
21 | }
22 |
23 | impl<'a, E, S, C, L> From[>> for DOMArenaRef<'a, E, S, C, L> {
24 | fn from(raw: Ref<'a, DOMNode>) -> Self {
25 | DOMArenaRef { raw }
26 | }
27 | }
28 |
29 | impl<'a, E, S, C, L> Deref for DOMArenaRef<'a, E, S, C, L> {
30 | type Target = DOMNode;
31 |
32 | fn deref(&self) -> &Self::Target {
33 | self.value()
34 | }
35 | }
36 |
37 | impl<'a, E, S, C, L> DOMArenaRef<'a, E, S, C, L> {
38 | pub(crate) fn value(&self) -> &'a DOMNode {
39 | self.raw.try_value().expect("Node deallocated")
40 | }
41 |
42 | pub(crate) fn into_value(self) -> &'a DOMNode {
43 | self.raw.try_into_value().expect("Node deallocated")
44 | }
45 |
46 | pub fn get(&self, id: DOMNodeId) -> DOMArenaRef<'a, E, S, C, L> {
47 | DOMArenaRef::from(self.raw.tree().get(id))
48 | }
49 |
50 | pub fn id(&self) -> DOMNodeId {
51 | self.raw.id()
52 | }
53 |
54 | pub fn parent_id(&self) -> Option> {
55 | self.raw.parent_id()
56 | }
57 |
58 | pub fn parent(&self) -> Option> {
59 | self.raw.parent().map(DOMArenaRef::from)
60 | }
61 |
62 | pub fn prev_sibling_id(&self) -> Option> {
63 | self.raw.prev_sibling_id()
64 | }
65 |
66 | pub fn prev_sibling(&self) -> Option> {
67 | self.raw.prev_sibling().map(DOMArenaRef::from)
68 | }
69 |
70 | pub fn next_sibling_id(&self) -> Option> {
71 | self.raw.next_sibling_id()
72 | }
73 |
74 | pub fn next_sibling(&self) -> Option> {
75 | self.raw.next_sibling().map(DOMArenaRef::from)
76 | }
77 |
78 | pub fn first_child_id(&self) -> Option> {
79 | self.raw.first_child_id()
80 | }
81 |
82 | pub fn first_child(&self) -> Option> {
83 | self.raw.first_child().map(DOMArenaRef::from)
84 | }
85 |
86 | pub fn last_child_id(&self) -> Option> {
87 | self.raw.last_child_id()
88 | }
89 |
90 | pub fn last_child(&self) -> Option> {
91 | self.raw.last_child().map(DOMArenaRef::from)
92 | }
93 |
94 | pub fn sibling_ids(&self) -> DOMNodeSiblingIds {
95 | self.raw.sibling_ids()
96 | }
97 |
98 | pub fn edge_ids(&self) -> DOMNodeEdgeIds {
99 | self.raw.edge_ids()
100 | }
101 |
102 | pub fn children_iter(&self) -> impl Iterator]- > {
103 | self.raw.children_values_iter()
104 | }
105 |
106 | pub fn descendants_iter(&self) -> impl Iterator
- > {
107 | self.raw.descendants_values_iter()
108 | }
109 |
110 | pub fn traverse_iter(&self) -> impl Iterator
- > {
111 | self.raw.traverse_values_iter()
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/rsx-dom/src/graph/node_ref_mut.rs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2016 Mozilla
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 | Unless required by applicable law or agreed to in writing, software distributed
7 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | specific language governing permissions and limitations under the License.
10 | */
11 |
12 | use std::ops::{Deref, DerefMut};
13 |
14 | use rsx_shared::traits::{TComputedStyles, TDOMNode, TGenericEvent, TLayoutNode, TStyleDeclarations};
15 | use rsx_tree::types::{Ref, RefMut};
16 |
17 | use types::{DOMArenaRef, DOMArenaRefMutPair, DOMNode, DOMNodeEdgeIds, DOMNodeId, DOMNodeIdPair, DOMNodeSiblingIds, DOMTree};
18 |
19 | #[derive(Debug, PartialEq)]
20 | pub struct DOMArenaRefMut<'a, E: 'a, S: 'a, C: 'a, L: 'a> {
21 | raw: RefMut<'a, DOMNode>
22 | }
23 |
24 | impl<'a, E, S, C, L> From>> for DOMArenaRefMut<'a, E, S, C, L> {
25 | fn from(raw: RefMut<'a, DOMNode>) -> Self {
26 | DOMArenaRefMut { raw }
27 | }
28 | }
29 |
30 | impl<'a, E, S, C, L> Into> for DOMArenaRefMut<'a, E, S, C, L> {
31 | fn into(self) -> DOMArenaRef<'a, E, S, C, L> {
32 | DOMArenaRef::from(Into::
[>>::into(self.raw))
33 | }
34 | }
35 |
36 | impl<'a, E, S, C, L> Deref for DOMArenaRefMut<'a, E, S, C, L> {
37 | type Target = DOMNode;
38 |
39 | fn deref(&self) -> &Self::Target {
40 | self.value()
41 | }
42 | }
43 |
44 | impl<'a, E, S, C, L> DerefMut for DOMArenaRefMut<'a, E, S, C, L> {
45 | fn deref_mut(&mut self) -> &mut Self::Target {
46 | self.value_mut()
47 | }
48 | }
49 |
50 | impl<'a, E, S, C, L> DOMArenaRefMut<'a, E, S, C, L> {
51 | pub(crate) fn value(&self) -> &DOMNode {
52 | self.raw.try_value().expect("Node deallocated")
53 | }
54 |
55 | pub(crate) fn value_mut(&mut self) -> &mut DOMNode {
56 | self.raw.try_value_mut().expect("Node deallocated")
57 | }
58 |
59 | pub(crate) fn into_value(self) -> &'a mut DOMNode {
60 | self.raw.try_into_value().expect("Node deallocated")
61 | }
62 |
63 | pub fn get(&mut self, id: DOMNodeId) -> DOMArenaRef {
64 | DOMArenaRef::from(self.raw.tree().get(id))
65 | }
66 |
67 | pub fn get_mut(&mut self, id: DOMNodeId) -> DOMArenaRefMut {
68 | DOMArenaRefMut::from(self.raw.tree_mut().get_mut(id))
69 | }
70 |
71 | pub fn get_mut_pair(&mut self, ids: DOMNodeIdPair) -> DOMArenaRefMutPair {
72 | DOMArenaRefMutPair::from(self.raw.tree_mut().get_mut_pair(ids))
73 | }
74 |
75 | pub fn get_mut_self_and(&mut self, id: DOMNodeId) -> DOMArenaRefMutPair {
76 | let ids = (self.id(), id);
77 | DOMArenaRefMutPair::from(self.raw.tree_mut().get_mut_pair(ids))
78 | }
79 |
80 | pub fn id(&self) -> DOMNodeId {
81 | self.raw.id()
82 | }
83 |
84 | pub fn parent_id(&self) -> Option> {
85 | self.raw.parent_id()
86 | }
87 |
88 | pub fn parent(&mut self) -> Option> {
89 | self.raw.parent().map(DOMArenaRefMut::from)
90 | }
91 |
92 | pub fn prev_sibling_id(&self) -> Option> {
93 | self.raw.prev_sibling_id()
94 | }
95 |
96 | pub fn prev_sibling(&mut self) -> Option> {
97 | self.raw.prev_sibling().map(DOMArenaRefMut::from)
98 | }
99 |
100 | pub fn next_sibling_id(&self) -> Option> {
101 | self.raw.next_sibling_id()
102 | }
103 |
104 | pub fn next_sibling(&mut self) -> Option> {
105 | self.raw.next_sibling().map(DOMArenaRefMut::from)
106 | }
107 |
108 | pub fn first_child_id(&self) -> Option> {
109 | self.raw.first_child_id()
110 | }
111 |
112 | pub fn first_child(&mut self) -> Option> {
113 | self.raw.first_child().map(DOMArenaRefMut::from)
114 | }
115 |
116 | pub fn last_child_id(&self) -> Option> {
117 | self.raw.last_child_id()
118 | }
119 |
120 | pub fn last_child(&mut self) -> Option> {
121 | self.raw.last_child().map(DOMArenaRefMut::from)
122 | }
123 |
124 | pub fn sibling_ids(&self) -> DOMNodeSiblingIds]