Zig 0.17.0-dev (Split by item)
This is an example of documentation generated by
ZigDoc , an alternative to Zig's built-in
Auto Doc feature. See also
examples in other modes/formats . The project being documented here (as the example) is the Zig library itself.
Zig › std/ › enums.zig › EnumIndexer
EnumIndexer
enums.EnumIndexer
pub fn EnumIndexer (comptime E : type ) type
File
Code
pub fn EnumIndexer (comptime E : type ) type {
const fields_len = @typeInfo (E ).@"enum" .field_names .len ;
@setEvalBranchQuota (3 * fields_len * std .math .log2 (@max (fields_len , 1 )) + eval_branch_quota_cushion );
if (@typeInfo (E ).@"enum" .mode == .nonexhaustive ) {
const BackingInt = @typeInfo (E ).@"enum" .tag_type ;
if (@bitSizeOf (BackingInt ) > @bitSizeOf (usize ))
@compileError ("Cannot create an enum indexer for a given non-exhaustive enum, tag_type is larger than usize." );
return struct {
pub const Key : type = E ;
const backing_int_sign = @typeInfo (BackingInt ).int .signedness ;
const min_value = std .math .minInt (BackingInt );
const max_value = std .math .maxInt (BackingInt );
const RangeType = @Int (.unsigned , @bitSizeOf (BackingInt ));
pub const count : comptime_int = std .math .maxInt (RangeType ) + 1 ;
pub fn indexOf (e : E ) usize {
if (backing_int_sign == .unsigned )
return @backingInt (e );
return if (@backingInt (e ) < 0 )
@intCast (@backingInt (e ) - min_value )
else
@as (RangeType , -min_value ) + @as (RangeType , @intCast (@backingInt (e )));
}
pub fn keyForIndex (i : usize ) E {
if (backing_int_sign == .unsigned )
return @fromBackingInt (@intCast (i ));
return @fromBackingInt (@intCast (@as (@Int (.signed , @bitSizeOf (RangeType ) + 1 ), @intCast (i )) + min_value ));
}
};
}
if (fields_len == 0 ) {
return struct {
pub const Key = E ;
pub const count : comptime_int = 0 ;
pub fn indexOf (e : E ) usize {
_ = e ;
unreachable ;
}
pub fn keyForIndex (i : usize ) E {
_ = i ;
unreachable ;
}
};
}
var field_values = @typeInfo (E ).@"enum" .field_values [0 ..fields_len ].*;
std .mem .sortUnstable (comptime_int , &field_values , {}, struct {
fn lessThan (_ : void , a : comptime_int , b : comptime_int ) bool {
return a < b ;
}
}.lessThan );
const min = field_values [0 ];
const max = field_values [fields_len - 1 ];
if (max - min == field_values .len - 1 ) {
return struct {
pub const Key = E ;
pub const count : comptime_int = fields_len ;
pub fn indexOf (e : E ) usize {
return @as (usize , @intCast (@backingInt (e ) - min ));
}
pub fn keyForIndex (i : usize ) E {
// gives up some safety to avoid artificially limiting
// the range of signed enum values to max_isize.
const enum_value = if (min < 0 ) @as (isize , @bitCast (i )) +% min else i + min ;
return @as (E , @fromBackingInt (@intCast (@as (@typeInfo (E ).@"enum" .tag_type , @intCast (enum_value )))));
}
};
}
const keys = valuesFromFields (E , &field_values );
return struct {
pub const Key = E ;
pub const count : comptime_int = fields_len ;
pub fn indexOf (e : E ) usize {
for (keys , 0 ..) |k , i | {
if (k == e ) return i ;
}
unreachable ;
}
pub fn keyForIndex (i : usize ) E {
return keys [i ];
}
};
}