//  Copyright (C) 2020 Éloïs SANCHEZ.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

//! Provide base16 convertion tools

use crate::bases::BaseConvertionError;

/// Convert a hexadecimal string in an array of 32 bytes.
///
/// The hex string must only contains hex characters
/// and produce a 32 bytes value.
pub fn str_hex_to_32bytes(text: &str) -> Result<[u8; 32], BaseConvertionError> {
    if text.len() != 64 {
        Err(BaseConvertionError::InvalidLength {
            expected: 64,
            found: text.len(),
        })
    } else {
        let mut bytes = [0u8; 32];

        let chars: Vec<char> = text.chars().collect();

        for i in 0..64 {
            if i % 2 != 0 {
                continue;
            }

            let byte1 = chars[i].to_digit(16);
            let byte2 = chars[i + 1].to_digit(16);

            if let Some(byte1) = byte1 {
                if let Some(byte2) = byte2 {
                    let byte = ((byte1 as u8) << 4) | byte2 as u8;
                    bytes[i / 2] = byte;
                } else {
                    return Err(BaseConvertionError::InvalidCharacter {
                        character: chars[i + 1],
                        offset: i + 1,
                    });
                }
            } else {
                return Err(BaseConvertionError::InvalidCharacter {
                    character: chars[i],
                    offset: i,
                });
            }
        }

        Ok(bytes)
    }
}