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
use std::{ffi::CStr, ops::Deref};

use crate::{ffi, type_id::TypeId};

#[derive(Debug)]
pub struct LogicalTypeHandle(ffi::duckdb_logical_type);

impl LogicalTypeHandle {
    pub unsafe fn from_raw(handle: ffi::duckdb_logical_type) -> Self {
        Self(handle)
    }
    pub unsafe fn from_id(type_: TypeId) -> Self {
        Self::from_raw(ffi::duckdb_create_logical_type(type_.to_raw()))
    }
    pub fn type_id(&self) -> Option<TypeId> {
        unsafe { TypeId::from_raw(ffi::duckdb_get_type_id(self.0)) }
    }
    pub unsafe fn decimal_width(&self) -> u8 {
        ffi::duckdb_decimal_width(self.0)
    }
    pub unsafe fn decimal_scale(&self) -> u8 {
        ffi::duckdb_decimal_scale(self.0)
    }
    pub unsafe fn enum_internal_type(&self) -> TypeId {
        TypeId::from_raw(ffi::duckdb_enum_internal_type(self.0)).expect("invalid type")
    }
    pub unsafe fn enum_dictionary_size(&self) -> u32 {
        ffi::duckdb_enum_dictionary_size(self.0)
    }
    pub unsafe fn enum_dictionary_value(&self, index: u64) -> String {
        let p = ffi::duckdb_enum_dictionary_value(self.0, index);
        let name = CStr::from_ptr(p).to_string_lossy().into_owned();
        ffi::duckdb_free(p as _);
        name
    }
    pub unsafe fn list_type_child_type(&self) -> LogicalTypeHandle {
        LogicalTypeHandle::from_raw(ffi::duckdb_list_type_child_type(self.0))
    }
    pub unsafe fn map_type_key_type(&self) -> LogicalTypeHandle {
        LogicalTypeHandle::from_raw(ffi::duckdb_map_type_key_type(self.0))
    }
    pub unsafe fn map_type_value_type(&self) -> LogicalTypeHandle {
        LogicalTypeHandle::from_raw(ffi::duckdb_map_type_value_type(self.0))
    }
    pub unsafe fn struct_type_child_count(&self) -> u64 {
        ffi::duckdb_struct_type_child_count(self.0)
    }
    pub unsafe fn struct_type_child_name(&self, index: u64) -> String {
        let p = ffi::duckdb_struct_type_child_name(self.0, index);
        let name = CStr::from_ptr(p).to_string_lossy().into_owned();
        ffi::duckdb_free(p as _);
        name
    }
    pub unsafe fn struct_type_child_type(&self, index: u64) -> LogicalTypeHandle {
        LogicalTypeHandle::from_raw(ffi::duckdb_struct_type_child_type(self.0, index))
    }
    pub unsafe fn union_type_member_count(&self) -> u64 {
        ffi::duckdb_union_type_member_count(self.0)
    }
    pub unsafe fn union_type_member_name(&self, index: u64) -> String {
        let p = ffi::duckdb_union_type_member_name(self.0, index);
        let name = CStr::from_ptr(p).to_string_lossy().into_owned();
        ffi::duckdb_free(p as _);
        name
    }
    pub unsafe fn union_type_member_type(&self, index: u64) -> LogicalTypeHandle {
        LogicalTypeHandle::from_raw(ffi::duckdb_union_type_member_type(self.0, index))
    }
}

impl Deref for LogicalTypeHandle {
    type Target = ffi::duckdb_logical_type;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl Drop for LogicalTypeHandle {
    fn drop(&mut self) {
        unsafe {
            ffi::duckdb_destroy_logical_type(&mut self.0);
        }
    }
}