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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use crate::{buffer, Document};

/// The index data type.
#[derive(Clone, Debug)]
pub enum IndexType {
    /// Corresponds to `GL_UNSIGNED_BYTE`.
    U8 = 5121,

    /// Corresponds to `GL_UNSIGNED_SHORT`.
    U16 = 5123,

    /// Corresponds to `GL_UNSIGNED_INT`.
    U32 = 5125,
}

/// Indices of those attributes that deviate from their initialization value.
pub struct Indices<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON struct.
    json: &'a json::accessor::sparse::Indices,
}

impl<'a> Indices<'a> {
    /// Constructs `sparse::Indices`.
    pub(crate) fn new(document: &'a Document, json: &'a json::accessor::sparse::Indices) -> Self {
        Self { document, json }
    }

    /// Returns the buffer view containing the sparse indices.
    pub fn view(&self) -> buffer::View<'a> {
        self.document
            .views()
            .nth(self.json.buffer_view.value())
            .unwrap()
    }

    /// The offset relative to the start of the parent buffer view in bytes.
    pub fn offset(&self) -> usize {
        self.json.byte_offset.0 as usize
    }

    /// The data type of each index.
    pub fn index_type(&self) -> IndexType {
        match self.json.component_type.unwrap().0 {
            json::accessor::ComponentType::U8 => IndexType::U8,
            json::accessor::ComponentType::U16 => IndexType::U16,
            json::accessor::ComponentType::U32 => IndexType::U32,
            _ => unreachable!(),
        }
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &'a json::Extras {
        &self.json.extras
    }
}

/// Sparse storage of attributes that deviate from their initialization value.
pub struct Sparse<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON struct.
    json: &'a json::accessor::sparse::Sparse,
}

impl<'a> Sparse<'a> {
    /// Constructs `Sparse`.
    pub(crate) fn new(document: &'a Document, json: &'a json::accessor::sparse::Sparse) -> Self {
        Self { document, json }
    }

    /// Returns the number of attributes encoded in this sparse accessor.
    pub fn count(&self) -> usize {
        self.json.count.0 as usize
    }

    /// Returns an index array of size `count` that points to those accessor
    /// attributes that deviate from their initialization value.
    pub fn indices(&self) -> Indices<'a> {
        Indices::new(self.document, &self.json.indices)
    }

    /// Returns an array of size `count * number_of_components`, storing the
    /// displaced accessor attributes pointed by `indices`.
    pub fn values(&self) -> Values<'a> {
        Values::new(self.document, &self.json.values)
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &'a json::Extras {
        &self.json.extras
    }
}

/// Array of size `count * number_of_components` storing the displaced accessor
/// attributes pointed by `accessor::sparse::Indices`.
pub struct Values<'a> {
    /// The parent `Document` struct.
    document: &'a Document,

    /// The corresponding JSON struct.
    json: &'a json::accessor::sparse::Values,
}

impl<'a> Values<'a> {
    /// Constructs `sparse::Values`.
    pub(crate) fn new(document: &'a Document, json: &'a json::accessor::sparse::Values) -> Self {
        Self { document, json }
    }

    /// Returns the buffer view containing the sparse values.
    pub fn view(&self) -> buffer::View<'a> {
        self.document
            .views()
            .nth(self.json.buffer_view.value())
            .unwrap()
    }

    /// The offset relative to the start of the parent buffer view in bytes.
    pub fn offset(&self) -> usize {
        self.json.byte_offset.0 as usize
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &'a json::Extras {
        &self.json.extras
    }
}

impl IndexType {
    /// Returns the number of bytes this value represents.
    pub fn size(&self) -> usize {
        use self::IndexType::*;
        match *self {
            U8 => 1,
            U16 => 2,
            U32 => 4,
        }
    }
}