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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
use crate::result::*;
use std::convert::TryFrom;
pub use std::convert::TryInto;

#[derive(Debug, Clone)]
pub struct BoundingBox {
    pub min: [f64; 3],
    pub max: [f64; 3],
}

#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PodType {
    Boolean = 0,
    U8,
    I8,

    U16,
    I16,

    U32,
    I32,

    U64,
    I64,

    F16,
    F32,
    F64,

    String,
    WString,

    Unknown = 127,
}

impl TryFrom<u32> for PodType {
    type Error = OgawaError;

    fn try_from(v: u32) -> Result<Self, Self::Error> {
        match v {
            x if x == PodType::Boolean as u32 => Ok(PodType::Boolean),
            x if x == PodType::U8 as u32 => Ok(PodType::U8),
            x if x == PodType::I8 as u32 => Ok(PodType::I8),
            x if x == PodType::U16 as u32 => Ok(PodType::U16),
            x if x == PodType::I16 as u32 => Ok(PodType::I16),
            x if x == PodType::U32 as u32 => Ok(PodType::U32),
            x if x == PodType::I32 as u32 => Ok(PodType::I32),
            x if x == PodType::U64 as u32 => Ok(PodType::U64),
            x if x == PodType::I64 as u32 => Ok(PodType::I64),

            x if x == PodType::F16 as u32 => Ok(PodType::F16),
            x if x == PodType::F32 as u32 => Ok(PodType::F32),
            x if x == PodType::F64 as u32 => Ok(PodType::F64),

            x if x == PodType::String as u32 => Ok(PodType::String),
            x if x == PodType::WString as u32 => Ok(PodType::WString),

            x if x == PodType::Unknown as u32 => Ok(PodType::Unknown),

            _ => Err(ParsingError::UnsupportedAlembicFile.into()),
        }
    }
}

#[derive(Debug)]
pub enum PodArray {
    Boolean(Vec<bool>),
    U8(Vec<u8>),
    I8(Vec<i8>),

    U16(Vec<u16>),
    I16(Vec<i16>),

    U32(Vec<u32>),
    I32(Vec<i32>),

    U64(Vec<u64>),
    I64(Vec<i64>),

    F16(Vec<half::f16>),
    F32(Vec<f32>),
    F64(Vec<f64>),

    String(Vec<String>),
    WString(Vec<String>),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DataType {
    pub(crate) pod_type: PodType,
    pub(crate) extent: u8,
}

pub fn chunk_vector_by_2<T>(mut vector: Vec<T>) -> Result<Vec<[T; 2]>, InternalError> {
    const CHUNK_BY: usize = 2;
    let raw_ptr = vector.as_mut_ptr();
    let len = vector.len();
    let capacity = vector.capacity();

    if len % CHUNK_BY != 0
        || capacity % CHUNK_BY != 0
        || std::mem::align_of::<T>() != std::mem::align_of::<[T; 2]>()
    {
        return Err(InternalError::InvalidChunkBy);
    }
    let vector = unsafe {
        std::mem::forget(vector);
        Vec::from_raw_parts(raw_ptr as *mut _, len / CHUNK_BY, capacity / CHUNK_BY)
    };

    Ok(vector)
}

pub fn chunk_vector_by_3<T>(mut vector: Vec<T>) -> Result<Vec<[T; 3]>, InternalError> {
    const CHUNK_BY: usize = 3;
    let raw_ptr = vector.as_mut_ptr();
    let len = vector.len();
    let capacity = vector.capacity();

    if len % CHUNK_BY != 0
        || capacity % CHUNK_BY != 0
        || std::mem::align_of::<T>() != std::mem::align_of::<[T; 3]>()
    {
        return Err(InternalError::InvalidChunkBy);
    }

    let vector = unsafe {
        std::mem::forget(vector);
        Vec::from_raw_parts(raw_ptr as *mut _, len / CHUNK_BY, capacity / CHUNK_BY)
    };

    Ok(vector)
}

pub fn chunk_vector_by_4<T>(mut vector: Vec<T>) -> Result<Vec<[T; 4]>, InternalError> {
    const CHUNK_BY: usize = 4;
    let raw_ptr = vector.as_mut_ptr();
    let len = vector.len();
    let capacity = vector.capacity();

    if len % CHUNK_BY != 0
        || capacity % CHUNK_BY != 0
        || std::mem::align_of::<T>() != std::mem::align_of::<[T; 4]>()
    {
        return Err(InternalError::InvalidChunkBy);
    }

    let vector = unsafe {
        std::mem::forget(vector);
        Vec::from_raw_parts(raw_ptr as *mut _, len / CHUNK_BY, capacity / CHUNK_BY)
    };

    Ok(vector)
}

pub const BOOL_TYPE: DataType = DataType {
    pod_type: PodType::Boolean,
    extent: 1,
};

pub const U8_TYPE: DataType = DataType {
    pod_type: PodType::U8,
    extent: 1,
};

pub const I32_TYPE: DataType = DataType {
    pod_type: PodType::I32,
    extent: 1,
};
pub const I32X2_TYPE: DataType = DataType {
    pod_type: PodType::I32,
    extent: 2,
};
pub const I32X3_TYPE: DataType = DataType {
    pod_type: PodType::I32,
    extent: 3,
};
pub const I32X4_TYPE: DataType = DataType {
    pod_type: PodType::I32,
    extent: 4,
};

pub const F32_TYPE: DataType = DataType {
    pod_type: PodType::F32,
    extent: 1,
};
pub const F32X2_TYPE: DataType = DataType {
    pod_type: PodType::F32,
    extent: 2,
};
pub const F32X3_TYPE: DataType = DataType {
    pod_type: PodType::F32,
    extent: 3,
};
pub const F32X4_TYPE: DataType = DataType {
    pod_type: PodType::F32,
    extent: 4,
};

pub const BOX_TYPE: DataType = DataType {
    pod_type: PodType::F64,
    extent: 6,
};