// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
"io"
)
/**
* Compressed Macintosh resource data,
* as stored in resources with the "compressed" attribute.
*
* Resource decompression is not documented by Apple.
* It is mostly used internally in System 7,
* some of Apple's own applications (such as ResEdit),
* and also by some third-party applications.
* Later versions of Classic Mac OS make less use of resource compression,
* but still support it fully for backwards compatibility.
* Carbon in Mac OS X no longer supports resource compression in any way.
*
* The data of all compressed resources starts with a common header,
* followed by the compressed data.
* The data is decompressed using code in a `'dcmp'` resource.
* Some decompressors used by Apple are included in the System file,
* but applications can also include custom decompressors.
* The header of the compressed data indicates the ID of the `'dcmp'` resource used to decompress the data,
* along with some parameters for the decompressor.
* @see Source
* @see Source
* @see Source
*/
type CompressedResource struct {
Header *CompressedResource_Header
CompressedData []byte
_io *kaitai.Stream
_root *CompressedResource
_parent interface{}
}
func NewCompressedResource() *CompressedResource {
return &CompressedResource{
}
}
func (this *CompressedResource) Read(io *kaitai.Stream, parent interface{}, root *CompressedResource) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1 := NewCompressedResource_Header()
err = tmp1.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Header = tmp1
tmp2, err := this._io.ReadBytesFull()
if err != nil {
return err
}
tmp2 = tmp2
this.CompressedData = tmp2
return err
}
/**
* The header of the compressed data.
*/
/**
* The compressed resource data.
*
* The format of this data is completely dependent on the decompressor and its parameters,
* as specified in the header.
* For details about the compressed data formats implemented by Apple's decompressors,
* see the specs in the resource_compression subdirectory.
*/
/**
* Compressed resource data header,
* as stored at the start of all compressed resources.
*/
type CompressedResource_Header struct {
CommonPart *CompressedResource_Header_CommonPart
TypeSpecificPartRawWithIo *BytesWithIo
_io *kaitai.Stream
_root *CompressedResource
_parent *CompressedResource
_raw_TypeSpecificPartRawWithIo []byte
_f_typeSpecificPartRaw bool
typeSpecificPartRaw []byte
_f_typeSpecificPart bool
typeSpecificPart interface{}
}
func NewCompressedResource_Header() *CompressedResource_Header {
return &CompressedResource_Header{
}
}
func (this *CompressedResource_Header) Read(io *kaitai.Stream, parent *CompressedResource, root *CompressedResource) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp3 := NewCompressedResource_Header_CommonPart()
err = tmp3.Read(this._io, this, this._root)
if err != nil {
return err
}
this.CommonPart = tmp3
tmp4, err := this._io.ReadBytes(int((this.CommonPart.LenHeader - 12)))
if err != nil {
return err
}
tmp4 = tmp4
this._raw_TypeSpecificPartRawWithIo = tmp4
_io__raw_TypeSpecificPartRawWithIo := kaitai.NewStream(bytes.NewReader(this._raw_TypeSpecificPartRawWithIo))
tmp5 := NewBytesWithIo()
err = tmp5.Read(_io__raw_TypeSpecificPartRawWithIo, this, nil)
if err != nil {
return err
}
this.TypeSpecificPartRawWithIo = tmp5
return err
}
/**
* The type-specific part of the header,
* as a raw byte array.
*/
func (this *CompressedResource_Header) TypeSpecificPartRaw() (v []byte, err error) {
if (this._f_typeSpecificPartRaw) {
return this.typeSpecificPartRaw, nil
}
this.typeSpecificPartRaw = []byte(this.TypeSpecificPartRawWithIo.Data)
this._f_typeSpecificPartRaw = true
return this.typeSpecificPartRaw, nil
}
/**
* The type-specific part of the header,
* parsed according to the type from the common part.
*/
func (this *CompressedResource_Header) TypeSpecificPart() (v interface{}, err error) {
if (this._f_typeSpecificPart) {
return this.typeSpecificPart, nil
}
thisIo := this.TypeSpecificPartRawWithIo._io
_pos, err := thisIo.Pos()
if err != nil {
return nil, err
}
_, err = thisIo.Seek(int64(0), io.SeekStart)
if err != nil {
return nil, err
}
switch (this.CommonPart.HeaderType) {
case 8:
tmp6 := NewCompressedResource_Header_TypeSpecificPartType8()
err = tmp6.Read(thisIo, this, this._root)
if err != nil {
return nil, err
}
this.typeSpecificPart = tmp6
case 9:
tmp7 := NewCompressedResource_Header_TypeSpecificPartType9()
err = tmp7.Read(thisIo, this, this._root)
if err != nil {
return nil, err
}
this.typeSpecificPart = tmp7
}
_, err = thisIo.Seek(_pos, io.SeekStart)
if err != nil {
return nil, err
}
this._f_typeSpecificPart = true
this._f_typeSpecificPart = true
return this.typeSpecificPart, nil
}
/**
* The common part of the header.
* Among other things,
* this part contains the header type,
* which determines the format of the data in the type-specific part of the header.
*/
/**
* Use `type_specific_part_raw` instead,
* unless you need access to this field's `_io`.
*/
/**
* The common part of a compressed resource data header.
* The format of this part is the same for all compressed resources.
*/
type CompressedResource_Header_CommonPart struct {
Magic []byte
LenHeader uint16
HeaderType uint8
Unknown uint8
LenDecompressed uint32
_io *kaitai.Stream
_root *CompressedResource
_parent *CompressedResource_Header
}
func NewCompressedResource_Header_CommonPart() *CompressedResource_Header_CommonPart {
return &CompressedResource_Header_CommonPart{
}
}
func (this *CompressedResource_Header_CommonPart) Read(io *kaitai.Stream, parent *CompressedResource_Header, root *CompressedResource) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp8, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp8 = tmp8
this.Magic = tmp8
if !(bytes.Equal(this.Magic, []uint8{168, 159, 101, 114})) {
return kaitai.NewValidationNotEqualError([]uint8{168, 159, 101, 114}, this.Magic, this._io, "/types/header/types/common_part/seq/0")
}
tmp9, err := this._io.ReadU2be()
if err != nil {
return err
}
this.LenHeader = uint16(tmp9)
if !(this.LenHeader == 18) {
return kaitai.NewValidationNotEqualError(18, this.LenHeader, this._io, "/types/header/types/common_part/seq/1")
}
tmp10, err := this._io.ReadU1()
if err != nil {
return err
}
this.HeaderType = tmp10
tmp11, err := this._io.ReadU1()
if err != nil {
return err
}
this.Unknown = tmp11
if !(this.Unknown == 1) {
return kaitai.NewValidationNotEqualError(1, this.Unknown, this._io, "/types/header/types/common_part/seq/3")
}
tmp12, err := this._io.ReadU4be()
if err != nil {
return err
}
this.LenDecompressed = uint32(tmp12)
return err
}
/**
* The signature of all compressed resource data.
*
* When interpreted as MacRoman, this byte sequence decodes to `®üer`.
*/
/**
* The byte length of the entire header (common and type-specific parts).
*
* The meaning of this field is mostly a guess,
* as all known header types result in a total length of `0x12`.
*/
/**
* Type of the header.
* This determines the format of the data in the type-specific part of the header.
*
* The only known header type values are `8` and `9`.
*
* Every known decompressor is only compatible with one of the header types
* (but every header type is used by more than one decompressor).
* Apple's decompressors with IDs 0 and 1 use header type 8,
* and those with IDs 2 and 3 use header type 9.
*/
/**
* The meaning of this field is not known.
* It has the value `0x01` in all known compressed resources.
*/
/**
* The byte length of the data after decompression.
*/
/**
* The type-specific part of a compressed resource header with header type `8`.
*/
type CompressedResource_Header_TypeSpecificPartType8 struct {
WorkingBufferFractionalSize uint8
ExpansionBufferSize uint8
DecompressorId int16
Reserved uint16
_io *kaitai.Stream
_root *CompressedResource
_parent *CompressedResource_Header
}
func NewCompressedResource_Header_TypeSpecificPartType8() *CompressedResource_Header_TypeSpecificPartType8 {
return &CompressedResource_Header_TypeSpecificPartType8{
}
}
func (this *CompressedResource_Header_TypeSpecificPartType8) Read(io *kaitai.Stream, parent *CompressedResource_Header, root *CompressedResource) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp13, err := this._io.ReadU1()
if err != nil {
return err
}
this.WorkingBufferFractionalSize = tmp13
tmp14, err := this._io.ReadU1()
if err != nil {
return err
}
this.ExpansionBufferSize = tmp14
tmp15, err := this._io.ReadS2be()
if err != nil {
return err
}
this.DecompressorId = int16(tmp15)
tmp16, err := this._io.ReadU2be()
if err != nil {
return err
}
this.Reserved = uint16(tmp16)
if !(this.Reserved == 0) {
return kaitai.NewValidationNotEqualError(0, this.Reserved, this._io, "/types/header/types/type_specific_part_type_8/seq/3")
}
return err
}
/**
* The ratio of the compressed data size to the uncompressed data size,
* times 256.
*
* This parameter affects the amount of memory allocated by the Resource Manager during decompression,
* but does not have a direct effect on the decompressor
* (except that it will misbehave if insufficient memory is provided).
* Alternative decompressors that decompress resources into a separate buffer rather than in-place can generally ignore this parameter.
*/
/**
* The maximum number of bytes that the compressed data might "grow" during decompression.
*
* This parameter affects the amount of memory allocated by the Resource Manager during decompression,
* but does not have a direct effect on the decompressor
* (except that it will misbehave if insufficient memory is provided).
* Alternative decompressors that decompress resources into a separate buffer rather than in-place can generally ignore this parameter.
*/
/**
* The ID of the `'dcmp'` resource that should be used to decompress this resource.
*/
/**
* The meaning of this field is not known.
* It has the value `0` in all known compressed resources,
* so it is most likely reserved.
*/
/**
* The type-specific part of a compressed resource header with header type `9`.
*/
type CompressedResource_Header_TypeSpecificPartType9 struct {
DecompressorId int16
DecompressorSpecificParametersWithIo *BytesWithIo
_io *kaitai.Stream
_root *CompressedResource
_parent *CompressedResource_Header
_raw_DecompressorSpecificParametersWithIo []byte
_f_decompressorSpecificParameters bool
decompressorSpecificParameters []byte
}
func NewCompressedResource_Header_TypeSpecificPartType9() *CompressedResource_Header_TypeSpecificPartType9 {
return &CompressedResource_Header_TypeSpecificPartType9{
}
}
func (this *CompressedResource_Header_TypeSpecificPartType9) Read(io *kaitai.Stream, parent *CompressedResource_Header, root *CompressedResource) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp17, err := this._io.ReadS2be()
if err != nil {
return err
}
this.DecompressorId = int16(tmp17)
tmp18, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp18 = tmp18
this._raw_DecompressorSpecificParametersWithIo = tmp18
_io__raw_DecompressorSpecificParametersWithIo := kaitai.NewStream(bytes.NewReader(this._raw_DecompressorSpecificParametersWithIo))
tmp19 := NewBytesWithIo()
err = tmp19.Read(_io__raw_DecompressorSpecificParametersWithIo, this, nil)
if err != nil {
return err
}
this.DecompressorSpecificParametersWithIo = tmp19
return err
}
/**
* Decompressor-specific parameters.
* The exact structure and meaning of this field is different for each decompressor.
*
* This field always has the same length,
* but decompressors don't always use the entirety of the field,
* so depending on the decompressor some parts of this field may be meaningless.
*/
func (this *CompressedResource_Header_TypeSpecificPartType9) DecompressorSpecificParameters() (v []byte, err error) {
if (this._f_decompressorSpecificParameters) {
return this.decompressorSpecificParameters, nil
}
this.decompressorSpecificParameters = []byte(this.DecompressorSpecificParametersWithIo.Data)
this._f_decompressorSpecificParameters = true
return this.decompressorSpecificParameters, nil
}
/**
* The ID of the `'dcmp'` resource that should be used to decompress this resource.
*/
/**
* Use `decompressor_specific_parameters` instead,
* unless you need access to this field's `_io`.
*/