<commit_before>use openvr_sys;
use openvr_sys::Enum_ETrackedPropertyError::*;

use subsystems::*;
use error::*;

/// Describes a string property of a tracked device
#[derive(Debug, Copy, Clone)]
pub enum TrackedDeviceStringProperty {
    TrackingSystemName,
    ModelNumber,
    SerialNumber,
    RenderModelName,
    ManufacturerName,
    TrackingFirmwareVersion,
    HardwareRevision,
    AllWirelessDongleDescriptions,
    ConnectedWirelessDongle,
    FirmwareManualUpdateURL,
    FirmwareProgrammingTarget,
    DisplayMCImageLeft,
    DisplayMCImageRight,
    DisplayGCImage,
    CameraFirmwareDescription,
    AttachedDeviceId,
    ModeLabel
}

impl TrackedDeviceStringProperty {
    pub fn to_raw(&self) -> openvr_sys::Enum_ETrackedDeviceProperty {
        use openvr_sys::Enum_ETrackedDeviceProperty::*;
        use self::TrackedDeviceStringProperty::*;

        match *self {
            TrackingSystemName => ETrackedDeviceProperty_Prop_TrackingSystemName_String,
            ModelNumber => ETrackedDeviceProperty_Prop_ModelNumber_String,
            SerialNumber => ETrackedDeviceProperty_Prop_SerialNumber_String,
            RenderModelName => ETrackedDeviceProperty_Prop_RenderModelName_String,
            ManufacturerName => ETrackedDeviceProperty_Prop_ManufacturerName_String,
            TrackingFirmwareVersion => ETrackedDeviceProperty_Prop_TrackingFirmwareVersion_String,
            HardwareRevision => ETrackedDeviceProperty_Prop_HardwareRevision_String,
            AllWirelessDongleDescriptions => ETrackedDeviceProperty_Prop_AllWirelessDongleDescriptions_String,
            ConnectedWirelessDongle => ETrackedDeviceProperty_Prop_ConnectedWirelessDongle_String,
            FirmwareManualUpdateURL => ETrackedDeviceProperty_Prop_Firmware_ManualUpdateURL_String,
            FirmwareProgrammingTarget => ETrackedDeviceProperty_Prop_Firmware_ProgrammingTarget_String,
            DisplayMCImageLeft => ETrackedDeviceProperty_Prop_DisplayMCImageLeft_String,
            DisplayMCImageRight => ETrackedDeviceProperty_Prop_DisplayMCImageRight_String,
            DisplayGCImage => ETrackedDeviceProperty_Prop_DisplayGCImage_String,
            CameraFirmwareDescription => ETrackedDeviceProperty_Prop_CameraFirmwareDescription_String,
            AttachedDeviceId => ETrackedDeviceProperty_Prop_AttachedDeviceId_String,
            ModeLabel => ETrackedDeviceProperty_Prop_ModeLabel_String
        }
    }
}

/// Describes the class of a tracked device
#[derive(Debug, Copy, Clone)]
pub enum TrackedDeviceClass {
    Invalid,
    HMD,
    Controller,
    TrackingReference,
    Other,
}

impl TrackedDeviceClass {
    pub fn to_raw(&self) -> openvr_sys::Enum_ETrackedDeviceClass {
        use self::TrackedDeviceClass::*;
        use openvr_sys::Enum_ETrackedDeviceClass::*;

        match *self {
            Invalid => ETrackedDeviceClass_TrackedDeviceClass_Invalid,
            HMD => ETrackedDeviceClass_TrackedDeviceClass_HMD,
            Controller => ETrackedDeviceClass_TrackedDeviceClass_Controller,
            TrackingReference => ETrackedDeviceClass_TrackedDeviceClass_TrackingReference,
            Other => ETrackedDeviceClass_TrackedDeviceClass_Other,
        }
    }

    pub fn from_raw(raw: openvr_sys::Enum_ETrackedDeviceClass) -> Self {
        use self::TrackedDeviceClass::*;
        use openvr_sys::Enum_ETrackedDeviceClass::*;

        match raw {
            ETrackedDeviceClass_TrackedDeviceClass_Invalid => Invalid,
            ETrackedDeviceClass_TrackedDeviceClass_HMD => HMD,
            ETrackedDeviceClass_TrackedDeviceClass_Controller => Controller,
            ETrackedDeviceClass_TrackedDeviceClass_TrackingReference => TrackingReference,
            ETrackedDeviceClass_TrackedDeviceClass_Other => Other,
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub struct TrackedDevicePose {
    pub index: usize,
    pub to_device: [[f32; 4]; 3],
    pub velocity: [f32; 3],
    pub angular_velocity: [f32; 3],
    pub is_valid: bool,
    pub is_connected: bool,
}

impl TrackedDevicePose {
    // returns the device class of the tracked object
    pub fn device_class(&self) -> TrackedDeviceClass {
        unsafe {
            let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable};
            TrackedDeviceClass::from_raw(system.GetTrackedDeviceClass.unwrap()(self.index as u32))
        }
    }

    /// gets a propery as a string
    pub fn get_property_string(&self, property: TrackedDeviceStringProperty) -> Result<String, Error<openvr_sys::Enum_ETrackedPropertyError>> {
        unsafe {
            let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable};

            let val_out = String::with_capacity(256);
            let mut err = ETrackedPropertyError_TrackedProp_Success;

            let size = system.GetStringTrackedDeviceProperty.unwrap()(
                self.index as u32,
                property.to_raw(),
                val_out.as_ptr() as *mut i8,
                256,
                &mut err
            );

            if size > 0 {
                return Ok(String::from_raw_parts(val_out.as_ptr() as *mut _, (size - 1) as usize, (size - 1) as usize));
            } else {
                return Err(Error::from_raw(err));
            }
        }
    }
}


#[derive(Debug, Copy, Clone)]
pub struct TrackedDevicePoses {
    pub count: usize,
    pub poses: [TrackedDevicePose; 16],
}

pub struct TrackedDevicePosesIterator<'a> {
    pub target: &'a TrackedDevicePoses,
    pub index: usize<commit_msg>fix for ffi string crash<commit_after>use openvr_sys;
use openvr_sys::Enum_ETrackedPropertyError::*;

use subsystems::*;
use error::*;
use std::slice;
use std::str;

/// Describes a string property of a tracked device
#[derive(Debug, Copy, Clone)]
pub enum TrackedDeviceStringProperty {
    TrackingSystemName,
    ModelNumber,
    SerialNumber,
    RenderModelName,
    ManufacturerName,
    TrackingFirmwareVersion,
    HardwareRevision,
    AllWirelessDongleDescriptions,
    ConnectedWirelessDongle,
    FirmwareManualUpdateURL,
    FirmwareProgrammingTarget,
    DisplayMCImageLeft,
    DisplayMCImageRight,
    DisplayGCImage,
    CameraFirmwareDescription,
    AttachedDeviceId,
    ModeLabel
}

impl TrackedDeviceStringProperty {
    pub fn to_raw(&self) -> openvr_sys::Enum_ETrackedDeviceProperty {
        use openvr_sys::Enum_ETrackedDeviceProperty::*;
        use self::TrackedDeviceStringProperty::*;

        match *self {
            TrackingSystemName => ETrackedDeviceProperty_Prop_TrackingSystemName_String,
            ModelNumber => ETrackedDeviceProperty_Prop_ModelNumber_String,
            SerialNumber => ETrackedDeviceProperty_Prop_SerialNumber_String,
            RenderModelName => ETrackedDeviceProperty_Prop_RenderModelName_String,
            ManufacturerName => ETrackedDeviceProperty_Prop_ManufacturerName_String,
            TrackingFirmwareVersion => ETrackedDeviceProperty_Prop_TrackingFirmwareVersion_String,
            HardwareRevision => ETrackedDeviceProperty_Prop_HardwareRevision_String,
            AllWirelessDongleDescriptions => ETrackedDeviceProperty_Prop_AllWirelessDongleDescriptions_String,
            ConnectedWirelessDongle => ETrackedDeviceProperty_Prop_ConnectedWirelessDongle_String,
            FirmwareManualUpdateURL => ETrackedDeviceProperty_Prop_Firmware_ManualUpdateURL_String,
            FirmwareProgrammingTarget => ETrackedDeviceProperty_Prop_Firmware_ProgrammingTarget_String,
            DisplayMCImageLeft => ETrackedDeviceProperty_Prop_DisplayMCImageLeft_String,
            DisplayMCImageRight => ETrackedDeviceProperty_Prop_DisplayMCImageRight_String,
            DisplayGCImage => ETrackedDeviceProperty_Prop_DisplayGCImage_String,
            CameraFirmwareDescription => ETrackedDeviceProperty_Prop_CameraFirmwareDescription_String,
            AttachedDeviceId => ETrackedDeviceProperty_Prop_AttachedDeviceId_String,
            ModeLabel => ETrackedDeviceProperty_Prop_ModeLabel_String
        }
    }
}

/// Describes the class of a tracked device
#[derive(Debug, Copy, Clone)]
pub enum TrackedDeviceClass {
    Invalid,
    HMD,
    Controller,
    TrackingReference,
    Other,
}

impl TrackedDeviceClass {
    pub fn to_raw(&self) -> openvr_sys::Enum_ETrackedDeviceClass {
        use self::TrackedDeviceClass::*;
        use openvr_sys::Enum_ETrackedDeviceClass::*;

        match *self {
            Invalid => ETrackedDeviceClass_TrackedDeviceClass_Invalid,
            HMD => ETrackedDeviceClass_TrackedDeviceClass_HMD,
            Controller => ETrackedDeviceClass_TrackedDeviceClass_Controller,
            TrackingReference => ETrackedDeviceClass_TrackedDeviceClass_TrackingReference,
            Other => ETrackedDeviceClass_TrackedDeviceClass_Other,
        }
    }

    pub fn from_raw(raw: openvr_sys::Enum_ETrackedDeviceClass) -> Self {
        use self::TrackedDeviceClass::*;
        use openvr_sys::Enum_ETrackedDeviceClass::*;

        match raw {
            ETrackedDeviceClass_TrackedDeviceClass_Invalid => Invalid,
            ETrackedDeviceClass_TrackedDeviceClass_HMD => HMD,
            ETrackedDeviceClass_TrackedDeviceClass_Controller => Controller,
            ETrackedDeviceClass_TrackedDeviceClass_TrackingReference => TrackingReference,
            ETrackedDeviceClass_TrackedDeviceClass_Other => Other,
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub struct TrackedDevicePose {
    pub index: usize,
    pub to_device: [[f32; 4]; 3],
    pub velocity: [f32; 3],
    pub angular_velocity: [f32; 3],
    pub is_valid: bool,
    pub is_connected: bool,
}

impl TrackedDevicePose {
    // returns the device class of the tracked object
    pub fn device_class(&self) -> TrackedDeviceClass {
        unsafe {
            let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable};
            TrackedDeviceClass::from_raw(system.GetTrackedDeviceClass.unwrap()(self.index as u32))
        }
    }

    /// gets a propery as a string
    pub fn get_property_string(&self, property: TrackedDeviceStringProperty) -> Result<String, Error<openvr_sys::Enum_ETrackedPropertyError>> {
        unsafe {
            let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable};

            let val_out = String::with_capacity(256);
            let mut err = ETrackedPropertyError_TrackedProp_Success;

            let size = system.GetStringTrackedDeviceProperty.unwrap()(
                self.index as u32,
                property.to_raw(),
                val_out.as_ptr() as *mut i8,
                256,
                &mut err
            );

            if size > 0 {
                let ptr = val_out.as_ptr() as *mut u8;
                let mem = slice::from_raw_parts(ptr, size as usize);
                let str = str::from_utf8(mem).unwrap();
                return Ok(String::from(str));
            } else {
                return Err(Error::from_raw(err));
            }
        }
    }
}


#[derive(Debug, Copy, Clone)]
pub struct TrackedDevicePoses {
    pub count: usize,
    pub poses: [TrackedDevicePose; 16],
}

pub struct TrackedDevicePosesIterator<'a> {
    pub target: &'a TrackedDevicePoses,
    pub index: usize
{'fraction_non_alphanumeric': 0.07422570309718761, 'fraction_numerical': 0.004983980064079744, 'mean_word_length': 3.297131931166348, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4844378', 'n_tokens_mistral': 3273, 'n_tokens_neox': 3217, 'n_words': 572}