diff --git a/ctru-rs/examples/camera-image.rs b/ctru-rs/examples/camera-image.rs index 45dcb13..de97712 100644 --- a/ctru-rs/examples/camera-image.rs +++ b/ctru-rs/examples/camera-image.rs @@ -1,9 +1,8 @@ use ctru::console::Console; -use ctru::gfx::{Screen, Side}; +use ctru::gfx::{Gfx, Screen, Side}; use ctru::services::cam::{Cam, CamOutputFormat, CamShutterSoundType, CamSize, Camera}; use ctru::services::hid::KeyPad; use ctru::services::{Apt, Hid}; -use ctru::Gfx; use std::time::Duration; const WIDTH: usize = 400; @@ -84,7 +83,7 @@ fn main() { .expect("Failed to take picture"); } - let img = convert_image_to_rgb8(&buf, 0, 0, WIDTH as usize, HEIGHT as usize); + let img = convert_image_to_rgb8(&buf, 0, 0, WIDTH, HEIGHT); unsafe { gfx.top_screen diff --git a/ctru-rs/src/error.rs b/ctru-rs/src/error.rs index 047f811..650ab7a 100644 --- a/ctru-rs/src/error.rs +++ b/ctru-rs/src/error.rs @@ -1,11 +1,48 @@ use std::error; use std::ffi::CStr; use std::fmt; +use std::ops::{ControlFlow, FromResidual, Try}; use ctru_sys::result::{R_DESCRIPTION, R_LEVEL, R_MODULE, R_SUMMARY}; pub type Result = ::std::result::Result; +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] +#[repr(transparent)] +pub(crate) struct ResultCode(pub ctru_sys::Result); + +impl Try for ResultCode { + type Output = (); + type Residual = Error; + + fn from_output(_: Self::Output) -> Self { + Self(0) + } + + fn branch(self) -> ControlFlow { + if self.0 < 0 { + ControlFlow::Break(self.into()) + } else { + ControlFlow::Continue(()) + } + } +} + +impl FromResidual for ResultCode { + fn from_residual(e: ::Residual) -> Self { + match e { + Error::Os(result) => Self(result), + _ => unreachable!(), + } + } +} + +impl FromResidual for Result { + fn from_residual(e: Error) -> Self { + Err(e) + } +} + /// The error type returned by all libctru functions. #[non_exhaustive] pub enum Error { @@ -39,6 +76,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: ResultCode) -> Self { + Self::Os(err.0) + } +} + impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index 70085e9..264d0ef 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -2,6 +2,7 @@ #![crate_name = "ctru"] #![feature(test)] #![feature(custom_test_frameworks)] +#![feature(try_trait_v2)] #![test_runner(test_runner::run)] extern "C" fn services_deinit() { diff --git a/ctru-rs/src/romfs.rs b/ctru-rs/src/romfs.rs index e054985..2a3def2 100644 --- a/ctru-rs/src/romfs.rs +++ b/ctru-rs/src/romfs.rs @@ -10,6 +10,7 @@ //! romfs_dir = "romfs" //! ``` +use crate::error::ResultCode; use once_cell::sync::Lazy; use std::ffi::CStr; use std::sync::Mutex; @@ -30,11 +31,7 @@ impl RomFS { true, || { let mount_name = CStr::from_bytes_with_nul(b"romfs\0").unwrap(); - let r = unsafe { ctru_sys::romfsMountSelf(mount_name.as_ptr()) }; - if r < 0 { - return Err(r.into()); - } - + ResultCode(unsafe { ctru_sys::romfsMountSelf(mount_name.as_ptr()) })?; Ok(()) }, || { diff --git a/ctru-rs/src/services/apt.rs b/ctru-rs/src/services/apt.rs index 4662a4e..2096a70 100644 --- a/ctru-rs/src/services/apt.rs +++ b/ctru-rs/src/services/apt.rs @@ -1,14 +1,12 @@ +use crate::error::ResultCode; + pub struct Apt(()); impl Apt { pub fn init() -> crate::Result { unsafe { - let r = ctru_sys::aptInit(); - if r < 0 { - Err(r.into()) - } else { - Ok(Apt(())) - } + ResultCode(ctru_sys::aptInit())?; + Ok(Apt(())) } } @@ -18,12 +16,8 @@ impl Apt { pub fn set_app_cpu_time_limit(&self, percent: u32) -> crate::Result<()> { unsafe { - let r = ctru_sys::APT_SetAppCpuTimeLimit(percent); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::APT_SetAppCpuTimeLimit(percent))?; + Ok(()) } } } diff --git a/ctru-rs/src/services/cam.rs b/ctru-rs/src/services/cam.rs index d8671ef..4339340 100644 --- a/ctru-rs/src/services/cam.rs +++ b/ctru-rs/src/services/cam.rs @@ -3,6 +3,7 @@ //! The CAM service provides access to the cameras. Cameras can return 2D images //! in the form of byte vectors which can be used for display or other usages. +use crate::error::ResultCode; use crate::services::gspgpu::FramebufferFormat; use bitflags::bitflags; use ctru_sys::Handle; @@ -267,24 +268,10 @@ impl BothOutwardCam { brightness_synchronization: bool, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetBrightnessSynchronization(brightness_synchronization); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } - } - } - - fn synchronize_vsync_timing(&self) -> crate::Result<()> { - unsafe { - let r = - ctru_sys::CAMU_SynchronizeVsyncTiming(ctru_sys::SELECT_OUT1, ctru_sys::SELECT_OUT2); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetBrightnessSynchronization( + brightness_synchronization, + ))?; + Ok(()) } } } @@ -313,12 +300,8 @@ pub trait Camera { fn is_busy(&self) -> crate::Result { unsafe { let mut is_busy = false; - let r = ctru_sys::CAMU_IsBusy(&mut is_busy, self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(is_busy) - } + ResultCode(ctru_sys::CAMU_IsBusy(&mut is_busy, self.port_as_raw()))?; + Ok(is_busy) } } @@ -327,12 +310,11 @@ pub trait Camera { fn get_transfer_bytes(&self) -> crate::Result { unsafe { let mut transfer_bytes = 0; - let r = ctru_sys::CAMU_GetTransferBytes(&mut transfer_bytes, self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(transfer_bytes) - } + ResultCode(ctru_sys::CAMU_GetTransferBytes( + &mut transfer_bytes, + self.port_as_raw(), + ))?; + Ok(transfer_bytes) } } @@ -340,12 +322,8 @@ pub trait Camera { /// [Camera::set_trimming_params] fn set_trimming(&mut self, enabled: bool) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetTrimming(self.port_as_raw(), enabled); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetTrimming(self.port_as_raw(), enabled))?; + Ok(()) } } @@ -353,30 +331,22 @@ pub trait Camera { fn is_trimming_enabled(&self) -> crate::Result { unsafe { let mut trimming = false; - let r = ctru_sys::CAMU_IsTrimming(&mut trimming, self.port_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(trimming) - } + ResultCode(ctru_sys::CAMU_IsTrimming(&mut trimming, self.port_as_raw()))?; + Ok(trimming) } } /// Sets trimming parameters based on coordinates specified inside a [CamTrimmingParams] fn set_trimming_params(&mut self, params: CamTrimmingParams) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetTrimmingParams( + ResultCode(ctru_sys::CAMU_SetTrimmingParams( self.port_as_raw(), params.x_start, params.y_start, params.x_end, params.y_end, - ); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ))?; + Ok(()) } } @@ -387,23 +357,20 @@ pub trait Camera { let mut y_start = 0; let mut x_end = 0; let mut y_end = 0; - let r = ctru_sys::CAMU_GetTrimmingParams( + ResultCode(ctru_sys::CAMU_GetTrimmingParams( &mut x_start, &mut y_start, &mut x_end, &mut y_end, self.port_as_raw(), - ); - if r < 0 { - Err(r.into()) - } else { - Ok(CamTrimmingParams { - x_start, - y_start, - x_end, - y_end, - }) - } + ))?; + + Ok(CamTrimmingParams { + x_start, + y_start, + x_end, + y_end, + }) } } @@ -418,42 +385,33 @@ pub trait Camera { cam_height: i16, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetTrimmingParamsCenter( + ResultCode(ctru_sys::CAMU_SetTrimmingParamsCenter( self.port_as_raw(), trim_width, trim_height, cam_width, cam_height, - ); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ))?; + Ok(()) } } /// Sets the exposure level of the camera fn set_exposure(&mut self, exposure: i8) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetExposure(self.camera_as_raw(), exposure); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetExposure(self.camera_as_raw(), exposure))?; + Ok(()) } } /// Sets the white balance mod of the camera based on the passed [CamWhiteBalance] argument fn set_white_balance(&mut self, white_balance: CamWhiteBalance) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetWhiteBalance(self.camera_as_raw(), white_balance.bits()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetWhiteBalance( + self.camera_as_raw(), + white_balance.bits(), + ))?; + Ok(()) } } @@ -464,39 +422,30 @@ pub trait Camera { white_balance: CamWhiteBalance, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetWhiteBalanceWithoutBaseUp( + ResultCode(ctru_sys::CAMU_SetWhiteBalanceWithoutBaseUp( self.camera_as_raw(), white_balance.bits(), - ); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ))?; + Ok(()) } } /// Sets the sharpness of the camera fn set_sharpness(&mut self, sharpness: i8) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetSharpness(self.camera_as_raw(), sharpness); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetSharpness(self.camera_as_raw(), sharpness))?; + Ok(()) } } /// Sets whether auto exposure is enabled or disabled for the camera fn set_auto_exposure(&mut self, enabled: bool) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetAutoExposure(self.camera_as_raw(), enabled); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetAutoExposure( + self.camera_as_raw(), + enabled, + ))?; + Ok(()) } } @@ -504,24 +453,22 @@ pub trait Camera { fn is_auto_exposure_enabled(&self) -> crate::Result { unsafe { let mut enabled = false; - let r = ctru_sys::CAMU_IsAutoExposure(&mut enabled, self.camera_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(enabled) - } + ResultCode(ctru_sys::CAMU_IsAutoExposure( + &mut enabled, + self.camera_as_raw(), + ))?; + Ok(enabled) } } /// Sets whether auto white balance is enabled or disabled for the camera fn set_auto_white_balance(&mut self, enabled: bool) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetAutoWhiteBalance(self.camera_as_raw(), enabled); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetAutoWhiteBalance( + self.camera_as_raw(), + enabled, + ))?; + Ok(()) } } @@ -529,25 +476,23 @@ pub trait Camera { fn is_auto_white_balance_enabled(&self) -> crate::Result { unsafe { let mut enabled = false; - let r = ctru_sys::CAMU_IsAutoWhiteBalance(&mut enabled, self.camera_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(enabled) - } + ResultCode(ctru_sys::CAMU_IsAutoWhiteBalance( + &mut enabled, + self.camera_as_raw(), + ))?; + Ok(enabled) } } /// Sets the flip direction of the camera's image based on the passed [CamFlip] argument fn flip_image(&mut self, flip: CamFlip) -> crate::Result<()> { unsafe { - let r = - ctru_sys::CAMU_FlipImage(self.camera_as_raw(), flip.bits(), ctru_sys::CONTEXT_A); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_FlipImage( + self.camera_as_raw(), + flip.bits(), + ctru_sys::CONTEXT_A, + ))?; + Ok(()) } } @@ -571,7 +516,7 @@ pub trait Camera { crop_1: (i16, i16), ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetDetailSize( + ResultCode(ctru_sys::CAMU_SetDetailSize( self.camera_as_raw(), width, height, @@ -580,48 +525,42 @@ pub trait Camera { crop_1.0, crop_1.1, ctru_sys::CONTEXT_A, - ); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ))?; + Ok(()) } } /// Sets the view size of the camera based on the passed [CamSize] argument. fn set_view_size(&mut self, size: CamSize) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetSize(self.camera_as_raw(), size.bits(), ctru_sys::CONTEXT_A); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetSize( + self.camera_as_raw(), + size.bits(), + ctru_sys::CONTEXT_A, + ))?; + Ok(()) } } /// Sets the frame rate of the camera based on the passed [CamFrameRate] argument. fn set_frame_rate(&mut self, frame_rate: CamFrameRate) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetFrameRate(self.camera_as_raw(), frame_rate.bits()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetFrameRate( + self.camera_as_raw(), + frame_rate.bits(), + ))?; + Ok(()) } } /// Sets the photo mode of the camera based on the passed [CamPhotoMode] argument. fn set_photo_mode(&mut self, photo_mode: CamPhotoMode) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetPhotoMode(self.camera_as_raw(), photo_mode.bits()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetPhotoMode( + self.camera_as_raw(), + photo_mode.bits(), + ))?; + Ok(()) } } @@ -630,53 +569,46 @@ pub trait Camera { /// Multiple effects can be set at once by combining the bitflags of [CamEffect] fn set_effect(&mut self, effect: CamEffect) -> crate::Result<()> { unsafe { - let r = - ctru_sys::CAMU_SetEffect(self.camera_as_raw(), effect.bits(), ctru_sys::CONTEXT_A); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetEffect( + self.camera_as_raw(), + effect.bits(), + ctru_sys::CONTEXT_A, + ))?; + Ok(()) } } /// Sets the contrast of the camera based on the passed [CamContrast] argument. fn set_contrast(&mut self, contrast: CamContrast) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetContrast(self.camera_as_raw(), contrast.bits()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetContrast( + self.camera_as_raw(), + contrast.bits(), + ))?; + Ok(()) } } /// Sets the lens correction of the camera based on the passed [CamLensCorrection] argument. fn set_lens_correction(&mut self, lens_correction: CamLensCorrection) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetLensCorrection(self.camera_as_raw(), lens_correction.bits()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetLensCorrection( + self.camera_as_raw(), + lens_correction.bits(), + ))?; + Ok(()) } } /// Sets the output format of the camera based on the passed [CamOutputFormat] argument. fn set_output_format(&mut self, format: CamOutputFormat) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetOutputFormat( + ResultCode(ctru_sys::CAMU_SetOutputFormat( self.camera_as_raw(), format.bits(), ctru_sys::CONTEXT_A, - ); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ))?; + Ok(()) } } @@ -696,12 +628,14 @@ pub trait Camera { height: i16, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetAutoExposureWindow(self.camera_as_raw(), x, y, width, height); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetAutoExposureWindow( + self.camera_as_raw(), + x, + y, + width, + height, + ))?; + Ok(()) } } @@ -721,25 +655,22 @@ pub trait Camera { height: i16, ) -> crate::Result<()> { unsafe { - let r = - ctru_sys::CAMU_SetAutoWhiteBalanceWindow(self.camera_as_raw(), x, y, width, height); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetAutoWhiteBalanceWindow( + self.camera_as_raw(), + x, + y, + width, + height, + ))?; + Ok(()) } } /// Sets whether the noise filter should be enabled or disabled for the camera fn set_noise_filter(&mut self, enabled: bool) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetNoiseFilter(self.camera_as_raw(), enabled); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetNoiseFilter(self.camera_as_raw(), enabled))?; + Ok(()) } } @@ -750,12 +681,8 @@ pub trait Camera { data: ImageQualityCalibrationData, ) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetImageQualityCalibrationData(data.0); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetImageQualityCalibrationData(data.0))?; + Ok(()) } } @@ -763,12 +690,8 @@ pub trait Camera { fn get_image_quality_calibration_data(&self) -> crate::Result { unsafe { let mut data = ImageQualityCalibrationData::default(); - let r = ctru_sys::CAMU_GetImageQualityCalibrationData(&mut data.0); - if r < 0 { - Err(r.into()) - } else { - Ok(data) - } + ResultCode(ctru_sys::CAMU_GetImageQualityCalibrationData(&mut data.0))?; + Ok(data) } } @@ -776,12 +699,8 @@ pub trait Camera { // TODO: Explain sleep camera fn set_sleep_camera(&mut self) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_SetSleepCamera(self.camera_as_raw()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_SetSleepCamera(self.camera_as_raw()))?; + Ok(()) } } @@ -804,12 +723,12 @@ pub trait Camera { ) -> crate::Result> { let transfer_unit = unsafe { let mut buf_size = 0; - let r = ctru_sys::CAMU_GetMaxBytes(&mut buf_size, width as i16, height as i16); - if r < 0 { - Err(crate::Error::from(r)) - } else { - Ok(buf_size) - } + ResultCode(ctru_sys::CAMU_GetMaxBytes( + &mut buf_size, + width as i16, + height as i16, + ))?; + Ok::(buf_size) }?; let screen_size = u32::from(width) * u32::from(width) * 2; @@ -817,83 +736,40 @@ pub trait Camera { let mut buf = vec![0u8; usize::try_from(screen_size).unwrap()]; unsafe { - let r = ctru_sys::CAMU_SetTransferBytes( + ResultCode(ctru_sys::CAMU_SetTransferBytes( self.port_as_raw(), transfer_unit, width as i16, height as i16, - ); - if r < 0 { - return Err(r.into()); - } - }; - - unsafe { - let r = ctru_sys::CAMU_Activate(self.camera_as_raw()); - if r < 0 { - return Err(r.into()); - } - }; - - unsafe { - let r = ctru_sys::CAMU_ClearBuffer(self.port_as_raw()); - if r < 0 { - return Err(r.into()); - } + ))?; }; unsafe { - let r = ctru_sys::CAMU_StartCapture(self.port_as_raw()); - if r < 0 { - return Err(r.into()); - } + ResultCode(ctru_sys::CAMU_Activate(self.camera_as_raw()))?; + ResultCode(ctru_sys::CAMU_ClearBuffer(self.port_as_raw()))?; + ResultCode(ctru_sys::CAMU_StartCapture(self.port_as_raw()))?; }; let receive_event = unsafe { let mut completion_handle: Handle = 0; - let r = ctru_sys::CAMU_SetReceiving( + ResultCode(ctru_sys::CAMU_SetReceiving( &mut completion_handle, buf.as_mut_ptr() as *mut ::libc::c_void, self.port_as_raw(), screen_size, transfer_unit.try_into().unwrap(), - ); - if r < 0 { - Err(crate::Error::from(r)) - } else { - Ok(completion_handle) - } + ))?; + Ok::(completion_handle) }?; unsafe { - let r = ctru_sys::svcWaitSynchronization( + ResultCode(ctru_sys::svcWaitSynchronization( receive_event, timeout.as_nanos().try_into().unwrap(), - ); - if r < 0 { - return Err(r.into()); - } - }; - - unsafe { - let r = ctru_sys::CAMU_StopCapture(self.port_as_raw()); - if r < 0 { - return Err(r.into()); - } - }; - - unsafe { - let r = ctru_sys::svcCloseHandle(receive_event); - if r < 0 { - return Err(r.into()); - } - }; - - unsafe { - let r = ctru_sys::CAMU_Activate(ctru_sys::SELECT_NONE); - if r < 0 { - return Err(r.into()); - } + ))?; + ResultCode(ctru_sys::CAMU_StopCapture(self.port_as_raw()))?; + ResultCode(ctru_sys::svcCloseHandle(receive_event))?; + ResultCode(ctru_sys::CAMU_Activate(ctru_sys::SELECT_NONE))?; }; Ok(buf) @@ -910,29 +786,21 @@ impl Cam { /// rare in practice. pub fn init() -> crate::Result { unsafe { - let r = ctru_sys::camInit(); - if r < 0 { - Err(r.into()) - } else { - Ok(Cam { - inner_cam: InwardCam, - outer_right_cam: OutwardRightCam, - outer_left_cam: OutwardLeftCam, - both_outer_cams: BothOutwardCam, - }) - } + ResultCode(ctru_sys::camInit())?; + Ok(Cam { + inner_cam: InwardCam, + outer_right_cam: OutwardRightCam, + outer_left_cam: OutwardLeftCam, + both_outer_cams: BothOutwardCam, + }) } } /// Plays the specified sound based on the [CamShutterSoundType] argument pub fn play_shutter_sound(&self, sound: CamShutterSoundType) -> crate::Result<()> { unsafe { - let r = ctru_sys::CAMU_PlayShutterSound(sound.bits()); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::CAMU_PlayShutterSound(sound.bits()))?; + Ok(()) } } } diff --git a/ctru-rs/src/services/cfgu.rs b/ctru-rs/src/services/cfgu.rs index bc8d986..603db7e 100644 --- a/ctru-rs/src/services/cfgu.rs +++ b/ctru-rs/src/services/cfgu.rs @@ -2,6 +2,8 @@ //! //! This module contains basic methods to retrieve and change configuration from the console. +use crate::error::ResultCode; + #[derive(Copy, Clone, Debug)] #[repr(u32)] pub enum Region { @@ -60,77 +62,48 @@ impl Cfgu { /// as many times as desired and the service will not exit until all /// instances of Cfgu drop out of scope. pub fn init() -> crate::Result { - unsafe { - let r = ctru_sys::cfguInit(); - if r < 0 { - Err(r.into()) - } else { - Ok(Cfgu(())) - } - } + ResultCode(unsafe { ctru_sys::cfguInit() })?; + Ok(Cfgu(())) } /// Gets system region from secure info pub fn get_region(&self) -> crate::Result { let mut region: u8 = 0; - let r = unsafe { ctru_sys::CFGU_SecureInfoGetRegion(&mut region) }; - if r < 0 { - Err(r.into()) - } else { - // The system shouldn't give an invalid value - Ok(Region::try_from(region).unwrap()) - } + ResultCode(unsafe { ctru_sys::CFGU_SecureInfoGetRegion(&mut region) })?; + Ok(Region::try_from(region).unwrap()) } /// Gets system's model pub fn get_model(&self) -> crate::Result { let mut model: u8 = 0; - let r = unsafe { ctru_sys::CFGU_GetSystemModel(&mut model) }; - if r < 0 { - Err(r.into()) - } else { - // The system shouldn't give an invalid value - Ok(SystemModel::try_from(model).unwrap()) - } + ResultCode(unsafe { ctru_sys::CFGU_GetSystemModel(&mut model) })?; + Ok(SystemModel::try_from(model).unwrap()) } /// Gets system's language pub fn get_language(&self) -> crate::Result { let mut language: u8 = 0; - let r = unsafe { ctru_sys::CFGU_GetSystemLanguage(&mut language) }; - if r < 0 { - Err(r.into()) - } else { - // The system shouldn't give an invalid value - Ok(Language::try_from(language).unwrap()) - } + ResultCode(unsafe { ctru_sys::CFGU_GetSystemLanguage(&mut language) })?; + Ok(Language::try_from(language).unwrap()) } /// Checks if NFC is supported by the console pub fn is_nfc_supported(&self) -> crate::Result { let mut supported: bool = false; - let r = unsafe { ctru_sys::CFGU_IsNFCSupported(&mut supported) }; - if r < 0 { - Err(r.into()) - } else { - Ok(supported) - } + ResultCode(unsafe { ctru_sys::CFGU_IsNFCSupported(&mut supported) })?; + Ok(supported) } /// Check if the console is from the 2DS family (2DS, New2DS, New2DSXL) pub fn is_2ds_family(&self) -> crate::Result { let mut is_2ds_family: u8 = 0; - let r = unsafe { ctru_sys::CFGU_GetModelNintendo2DS(&mut is_2ds_family) }; - if r < 0 { - Err(r.into()) - } else { - Ok(is_2ds_family == 0) - } + ResultCode(unsafe { ctru_sys::CFGU_GetModelNintendo2DS(&mut is_2ds_family) })?; + Ok(is_2ds_family == 0) } } diff --git a/ctru-rs/src/services/hid.rs b/ctru-rs/src/services/hid.rs index 18790f1..6aacf3a 100644 --- a/ctru-rs/src/services/hid.rs +++ b/ctru-rs/src/services/hid.rs @@ -4,6 +4,7 @@ //! and circle pad information. It also provides information from the sound volume slider, //! the accelerometer, and the gyroscope. +use crate::error::ResultCode; bitflags::bitflags! { /// A set of flags corresponding to the button and directional pad /// inputs on the 3DS @@ -62,12 +63,8 @@ pub struct CirclePosition(ctru_sys::circlePosition); impl Hid { pub fn init() -> crate::Result { unsafe { - let r = ctru_sys::hidInit(); - if r < 0 { - Err(r.into()) - } else { - Ok(Hid(())) - } + ResultCode(ctru_sys::hidInit())?; + Ok(Hid(())) } } diff --git a/ctru-rs/src/services/ps.rs b/ctru-rs/src/services/ps.rs index 3b4ef1a..0e8cc5c 100644 --- a/ctru-rs/src/services/ps.rs +++ b/ctru-rs/src/services/ps.rs @@ -4,6 +4,8 @@ //! As such, it is initialized by default in `ctru::init` instead of having a safety handler //! See also +use crate::error::ResultCode; + #[repr(u32)] pub enum AESAlgorithm { CbcEnc, @@ -31,32 +33,22 @@ pub enum AESKeyType { pub fn local_friend_code_seed() -> crate::Result { let mut seed: u64 = 0; - let r = unsafe { ctru_sys::PS_GetLocalFriendCodeSeed(&mut seed) }; - if r < 0 { - Err(r.into()) - } else { - Ok(seed) - } + ResultCode(unsafe { ctru_sys::PS_GetLocalFriendCodeSeed(&mut seed) })?; + Ok(seed) } pub fn device_id() -> crate::Result { let mut id: u32 = 0; - let r = unsafe { ctru_sys::PS_GetDeviceId(&mut id) }; - if r < 0 { - Err(r.into()) - } else { - Ok(id) - } + ResultCode(unsafe { ctru_sys::PS_GetDeviceId(&mut id) })?; + Ok(id) } pub fn generate_random_bytes(out: &mut [u8]) -> crate::Result<()> { - let r = unsafe { ctru_sys::PS_GenerateRandomBytes(out as *mut _ as *mut _, out.len() as u32) }; - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(unsafe { + ctru_sys::PS_GenerateRandomBytes(out as *mut _ as *mut _, out.len() as u32) + })?; + Ok(()) } #[cfg(test)] diff --git a/ctru-rs/src/services/soc.rs b/ctru-rs/src/services/soc.rs index dad4188..88fb4aa 100644 --- a/ctru-rs/src/services/soc.rs +++ b/ctru-rs/src/services/soc.rs @@ -3,6 +3,7 @@ use once_cell::sync::Lazy; use std::net::Ipv4Addr; use std::sync::Mutex; +use crate::error::ResultCode; use crate::services::ServiceReference; use crate::Error; @@ -38,10 +39,7 @@ impl Soc { false, || { let soc_mem = unsafe { memalign(0x1000, num_bytes) } as *mut u32; - let r = unsafe { ctru_sys::socInit(soc_mem, num_bytes as u32) }; - if r < 0 { - return Err(r.into()); - } + ResultCode(unsafe { ctru_sys::socInit(soc_mem, num_bytes as u32) })?; Ok(()) }, diff --git a/ctru-rs/src/services/sslc.rs b/ctru-rs/src/services/sslc.rs index bdd5407..aa4d26f 100644 --- a/ctru-rs/src/services/sslc.rs +++ b/ctru-rs/src/services/sslc.rs @@ -1,29 +1,26 @@ // TODO: Implement remaining functions +use crate::error::ResultCode; + pub struct SslC(()); impl SslC { /// Initialize sslc pub fn init() -> crate::Result { unsafe { - let r = ctru_sys::sslcInit(0); - if r < 0 { - Err(r.into()) - } else { - Ok(SslC(())) - } + ResultCode(ctru_sys::sslcInit(0))?; + Ok(SslC(())) } } /// Fill `buf` with `buf.len()` random bytes pub fn generate_random_data(&self, buf: &mut [u8]) -> crate::Result<()> { unsafe { - let r = ctru_sys::sslcGenerateRandomData(buf.as_ptr() as _, buf.len() as u32); - if r < 0 { - Err(r.into()) - } else { - Ok(()) - } + ResultCode(ctru_sys::sslcGenerateRandomData( + buf.as_ptr() as _, + buf.len() as u32, + ))?; + Ok(()) } } }