cfsp 1.0.1

A JVM Bytecode Manipulation Framework inspired by ASM.
Documentation
use crate::node::access_flag::{
    ExportsAccessFlag, ModuleAccessFlag, OpensAccessFlag, RequiresAccessFlag,
};
#[allow(unused_imports)]
use bitflags::Flags;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::Read;

use crate::node::attribute::module::{Exports, Opens, Provides, Requires};
use crate::node::attribute::{Attribute, Module};
use crate::parse::error::ParseResult;

pub(super) fn module<R: Read>(input: &mut R) -> ParseResult<Option<Attribute>> {
    let module_name_index = input.read_u16::<BigEndian>()?;
    let module_flags = ModuleAccessFlag::from_bits_truncate(input.read_u16::<BigEndian>()?);
    let module_version_index = input.read_u16::<BigEndian>()?;
    let requires_count = input.read_u16::<BigEndian>()?;
    let mut requires = Vec::with_capacity(requires_count as usize);

    for _ in 0..requires_count {
        requires.push(parse_requires(input)?);
    }

    let exports_count = input.read_u16::<BigEndian>()?;
    let mut exports = Vec::with_capacity(exports_count as usize);

    for _ in 0..exports_count {
        exports.push(parse_exports(input)?);
    }

    let opens_count = input.read_u16::<BigEndian>()?;
    let mut opens = Vec::with_capacity(opens_count as usize);

    for _ in 0..opens_count {
        opens.push(parse_opens(input)?);
    }

    let uses_count = input.read_u16::<BigEndian>()?;
    let mut uses_index = vec![0; uses_count as usize];

    for i in 0..uses_count {
        uses_index[i as usize] = input.read_u16::<BigEndian>()?;
    }

    let provides_count = input.read_u16::<BigEndian>()?;
    let mut provides = Vec::with_capacity(provides_count as usize);

    for _ in 0..provides_count {
        provides.push(parse_provides(input)?);
    }

    Ok(Some(Attribute::Module(Module {
        module_name_index,
        module_flags,
        module_version_index,
        requires_count,
        requires,
        exports_count,
        exports,
        opens_count,
        opens,
        uses_count,
        uses_index,
        provides_count,
        provides,
    })))
}

#[inline(always)]
fn parse_requires<R: Read>(input: &mut R) -> ParseResult<Requires> {
    let requires_index = input.read_u16::<BigEndian>()?;
    let requires_flags = RequiresAccessFlag::from_bits_truncate(input.read_u16::<BigEndian>()?);
    let requires_version_index = input.read_u16::<BigEndian>()?;

    Ok(Requires {
        requires_index,
        requires_flags,
        requires_version_index,
    })
}

#[inline(always)]
fn parse_exports<R: Read>(input: &mut R) -> ParseResult<Exports> {
    let exports_index = input.read_u16::<BigEndian>()?;
    let exports_flags = ExportsAccessFlag::from_bits_truncate(input.read_u16::<BigEndian>()?);
    let exports_to_count = input.read_u16::<BigEndian>()?;
    let mut exports_to_index = vec![0; exports_to_count as usize];

    for i in 0..exports_to_count {
        exports_to_index[i as usize] = input.read_u16::<BigEndian>()?;
    }

    Ok(Exports {
        exports_index,
        exports_flags,
        exports_to_count,
        exports_to_index,
    })
}

#[inline(always)]
fn parse_opens<R: Read>(input: &mut R) -> ParseResult<Opens> {
    let opens_index = input.read_u16::<BigEndian>()?;
    let opens_flags = OpensAccessFlag::from_bits_truncate(input.read_u16::<BigEndian>()?);
    let opens_to_count = input.read_u16::<BigEndian>()?;
    let mut opens_to_index = vec![0; opens_to_count as usize];

    for i in 0..opens_to_count {
        opens_to_index[i as usize] = input.read_u16::<BigEndian>()?;
    }

    Ok(Opens {
        opens_index,
        opens_flags,
        opens_to_count,
        opens_to_index,
    })
}

#[inline(always)]
fn parse_provides<R: Read>(input: &mut R) -> ParseResult<Provides> {
    let provides_index = input.read_u16::<BigEndian>()?;
    let provides_with_count = input.read_u16::<BigEndian>()?;
    let mut provides_with_index = vec![0; provides_with_count as usize];

    for i in 0..provides_with_count {
        provides_with_index[i as usize] = input.read_u16::<BigEndian>()?;
    }

    Ok(Provides {
        provides_index,
        provides_with_count,
        provides_with_index,
    })
}