%% Generated by prepare_templates. DO NOT EDIT THIS FILE.
%%
%% Input file: asn1ct_eval_per.funcs

-module(asn1ct_eval_per).
-export([encode_constrained_number/2,
encode_small_number/1]).

eint(0, [B|Acc]) when B < 128 ->
    [B|Acc];
eint(N, Acc) ->
    eint(N bsr 8, [N band 255|Acc]).

eint_positive(Val) ->
    case eint(Val, []) of
        [0,B1|T] ->
            [B1|T];
        T ->
            T
    end.

encode_constrained_number({Lb,Ub}, Val) when Val >= Lb, Ub >= Val ->
    Range = Ub - Lb + 1,
    Val2 = Val - Lb,
    if
        Range == 1 ->
            [];
        Range == 2 ->
            [Val2];
        Range =< 4 ->
            [10,2,Val2];
        Range =< 8 ->
            [10,3,Val2];
        Range =< 16 ->
            [10,4,Val2];
        Range =< 32 ->
            [10,5,Val2];
        Range =< 64 ->
            [10,6,Val2];
        Range =< 128 ->
            [10,7,Val2];
        Range =< 255 ->
            [10,8,Val2];
        Range =< 256 ->
            [20,1,Val2];
        Range =< 65536 ->
            [20,2,<<Val2:16>>];
        Range =< 1 bsl 255 * 8 ->
            Octs = binary:encode_unsigned(Val2),
            RangeOcts = binary:encode_unsigned(Range - 1),
            OctsLen = byte_size(Octs),
            RangeOctsLen = byte_size(RangeOcts),
            LengthBitsNeeded = minimum_bits(RangeOctsLen - 1),
            [10,LengthBitsNeeded,OctsLen - 1,20,OctsLen,Octs];
        true ->
            exit({not_supported,{integer_range,Range}})
    end;
encode_constrained_number({_,_}, Val) ->
    exit({error,{asn1,{illegal_value,Val}}}).

encode_length(Len) ->
    if
        Len < 128 ->
            [20,1,Len];
        Len < 16384 ->
            <<20,2,2:2,Len:14>>;
        true ->
            exit({error,{asn1,{encode_length,{nyi,above_16k}}}})
    end.

encode_semi_constrained_number(Lb, Val) ->
    Val2 = Val - Lb,
    Oct = eint_positive(Val2),
    Len = length(Oct),
    if
        Len < 128 ->
            [20,Len + 1,Len|Oct];
        Len < 256 ->
            [encode_length(Len),20,Len|Oct];
        true ->
            [encode_length(Len),21,<<Len:16>>|Oct]
    end.

encode_small_number(Val) when Val < 64 ->
    [10,7,Val];
encode_small_number(Val) ->
    [1|encode_semi_constrained_number(0, Val)].

minimum_bits(N) when N < 4 ->
    2;
minimum_bits(N) when N < 8 ->
    3;
minimum_bits(N) when N < 16 ->
    4;
minimum_bits(N) when N < 32 ->
    5;
minimum_bits(N) when N < 64 ->
    6;
minimum_bits(N) when N < 128 ->
    7;
minimum_bits(_N) ->
    8.
