// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License..

//! # align box crate for Rust SGX SDK
//!

use super::alignalloc::AlignAlloc;
pub use super::alignalloc::AlignReq;
use alloc::alloc::handle_alloc_error;
use core::alloc::Layout;
use core::borrow;
use core::fmt;
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr;
use core::ptr::{NonNull, Unique};

pub struct AlignBox<T> {
    ptr: Unique<T>,
    align_layout: Layout,
    origin_layout: Layout,
}

impl<T> AlignBox<T> {
    /// Gets a raw pointer to the start of the allocation. Note that this is
    /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must
    /// be careful.
    pub fn as_ptr(&self) -> *mut T {
        self.ptr.as_ptr()
    }
}

impl<T> Deref for AlignBox<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { self.ptr.as_ref() }
    }
}

impl<T> DerefMut for AlignBox<T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { self.ptr.as_mut() }
    }
}

impl<T> AsRef<T> for AlignBox<T> {
    fn as_ref(&self) -> &T {
        &**self
    }
}

impl<T> AsMut<T> for AlignBox<T> {
    fn as_mut(&mut self) -> &mut T {
        &mut **self
    }
}

impl<T> borrow::Borrow<T> for AlignBox<T> {
    fn borrow(&self) -> &T {
        &**self
    }
}

impl<T> borrow::BorrowMut<T> for AlignBox<T> {
    fn borrow_mut(&mut self) -> &mut T {
        &mut **self
    }
}

impl<T: fmt::Display> fmt::Display for AlignBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<T: fmt::Debug> fmt::Debug for AlignBox<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AlignBox")
            .field("align_layout", &self.align_layout)
            .field("data", &**self)
            .finish()
    }
}

impl<T: Clone> Clone for AlignBox<T> {
    #[rustfmt::skip]
    #[inline]
    fn clone(&self) -> AlignBox<T> {
        let ptr = match unsafe {
            AlignAlloc.alloc_with_pad_align_zeroed(self.origin_layout, self.align_layout)
        } {
            Ok(p) => p,
            Err(_) => handle_alloc_error(self.align_layout),
        };
        unsafe {
            ptr::copy_nonoverlapping(
                &(**self).clone() as *const _ as *const u8,
                ptr.as_ptr(),
                self.origin_layout.size(),
            );
        }
        AlignBox {
            ptr: Unique::new(ptr.cast::<T>().as_ptr()).unwrap(),
            align_layout: self.align_layout,
            origin_layout: self.origin_layout,
        }
    }

    #[inline]
    fn clone_from(&mut self, source: &AlignBox<T>) {
        if source.align_layout.size() != self.align_layout.size() {
            let ptr = match unsafe {
                AlignAlloc.alloc_with_pad_align_zeroed(source.origin_layout, source.align_layout)
            } {
                Ok(p) => p,
                Err(_) => handle_alloc_error(source.align_layout),
            };
            unsafe {
                ptr::copy_nonoverlapping(
                    &(**source).clone() as *const _ as *const u8,
                    ptr.as_ptr(),
                    source.origin_layout.size(),
                );
                self.dealloc_buffer();
            }
            self.ptr = Unique::new(ptr.cast::<T>().as_ptr()).unwrap();
        } else {
            (**self).clone_from(&(**source));
        }
        self.align_layout = source.align_layout;
        self.origin_layout = source.origin_layout;
    }
}

impl<T> AlignBox<T> {
    unsafe fn dealloc_buffer(&mut self) {
        let elem_size = mem::size_of::<T>();
        if elem_size != 0 {
            AlignAlloc.dealloc(NonNull::from(self.ptr).cast(), self.origin_layout)
        }
    }
}

unsafe impl<#[may_dangle] T> Drop for AlignBox<T> {
    fn drop(&mut self) {
        unsafe {
            self.dealloc_buffer();
        }
    }
}

impl<T> AlignBox<T> {
    fn new_with_req_in(align: usize, align_req: &[AlignReq]) -> Option<AlignBox<T>> {
        if align_req.len() == 0 {
            AlignBox::new_in()
        } else {
            AlignBox::allocate_in(true, align, align_req)
        }
    }

    fn new_with_align_in(align: usize) -> Option<AlignBox<T>> {
        let v: [AlignReq; 1] = [AlignReq {
            offset: 0,
            len: mem::size_of::<T>(),
        }];
        AlignBox::allocate_in(true, align, &v)
    }

    fn new_in() -> Option<AlignBox<T>> {
        let v: [AlignReq; 1] = [AlignReq {
            offset: 0,
            len: mem::size_of::<T>(),
        }];
        AlignBox::allocate_in(true, mem::align_of::<T>(), &v)
    }

    fn allocate_in(zeroed: bool, align: usize, align_req: &[AlignReq]) -> Option<AlignBox<T>> {
        if mem::size_of::<T>() == 0 {
            return None;
        }

        let layout = match Layout::from_size_align(mem::size_of::<T>(), align) {
            Ok(n) => n,
            Err(_) => return None,
        };

        let align_layout = match AlignAlloc.pad_align_to(layout, align_req) {
            Ok(n) => n,
            Err(_) => return None,
        };

        // handles ZSTs and `cap = 0` alike
        let result = if zeroed {
            unsafe { AlignAlloc.alloc_with_req_zeroed(layout, align_req) }
        } else {
            unsafe { AlignAlloc.alloc_with_req(layout, align_req) }
        };
        let ptr = match result {
            Ok(p) => p,
            Err(_) => handle_alloc_error(align_layout),
        };

        Some(AlignBox {
            ptr: Unique::new(ptr.cast::<T>().as_ptr()).unwrap(),
            align_layout: align_layout,
            origin_layout: layout,
        })
    }
}

impl<T> AlignBox<T> {
    pub fn new() -> Option<AlignBox<T>> {
        Self::new_in()
    }
    pub fn new_with_align(align: usize) -> Option<AlignBox<T>> {
        Self::new_with_align_in(align)
    }
    pub fn new_with_req(align: usize, align_req: &[AlignReq]) -> Option<AlignBox<T>> {
        Self::new_with_req_in(align, align_req)
    }
}

impl<T> AlignBox<T> {
    pub fn heap_init<F>(initialize: F) -> Option<AlignBox<T>>
    where
        F: Fn(&mut T),
    {
        unsafe {
            let mut t = Self::new_in();
            match t {
                Some(ref mut b) => initialize(b.ptr.as_mut()),
                None => (),
            }
            t
        }
    }
    pub fn heap_init_with_align<F>(initialize: F, align: usize) -> Option<AlignBox<T>>
    where
        F: Fn(&mut T),
    {
        unsafe {
            let mut t = Self::new_with_align(align);
            match t {
                Some(ref mut b) => initialize(b.ptr.as_mut()),
                None => (),
            }
            t
        }
    }
    pub fn heap_init_with_req<F>(
        initialize: F,
        align: usize,
        data: &[AlignReq],
    ) -> Option<AlignBox<T>>
    where
        F: Fn(&mut T),
    {
        unsafe {
            let mut t = Self::new_with_req(align, data);
            match t {
                Some(ref mut b) => initialize(b.ptr.as_mut()),
                None => (),
            }
            t
        }
    }
}
