# Checking validity of enum value image without exception

**URL:** https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695
**Category:** General
**Tags:** ada
**Created:** [March 3, 2024, 6:24pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695 "2024-03-03T18:24:24Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![mosteo](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/mosteo/32/8_2.png) [@mosteo](https://forum.ada-lang.io/u/mosteo)
#### Post date: [March 3, 2024, 6:24pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/1 "2024-03-03T18:24:24Z")

</div>

Just double checking: is there any way to ascertain that a string can be converted to an enumeration value that does not involve raising an exception, i.e.:

```ada
begin
   return Some_Enum'Value ("asdf");
exception
   -- Invalid value, do whatever you must.
end;

```

I don’t think so as `'Valid` takes a variable of the type, but I might be missing something?

---

<div class="post-metadata">

### Author: ![Verisimilitude](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/verisimilitude/32/384_2.png) [@Verisimilitude](https://forum.ada-lang.io/u/Verisimilitude)
#### Post date: [March 3, 2024, 6:54pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/2 "2024-03-03T18:54:34Z")

</div>

If the enumeration only has a few values, consider getting the Image of each and comparing them to the string under consideration, after stripping it of extra whitespace and whatnot.

---

<div class="post-metadata">

### Author: ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)
#### Post date: [March 3, 2024, 9:05pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/3 "2024-03-03T21:05:54Z")

</div>

You would need an error enumeration in that case.

You could try to do a conversion and return true if successful and false on exception, that means you’d also need to do it twice unless you return the enum as an out parameter.

This is one area where an option type would be handy.

---

<div class="post-metadata">

### Author: ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)
#### Post date: [March 3, 2024, 10:54pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/4 "2024-03-03T22:54:16Z")

</div>

You can make a constant indefinite map with a key type of string and element type the enumeration. Then you can call .Contains() with a forced to upper on the input for a Boolean result.

It takes some scaffolding like a custom “&” operator to use to make the constant map and overriding contains to force the to upper but it is not terrible to do. I’ve done it for a compiler keyword search before.

If the enumeration is simple then you just insert the image of the enumeration value as the key

EDIT: Example:

```ada
    generic
        type Enumeration is (<>);
    package Enumeration_Search is 
    
        package Maps is new Ada.Containers.Indefinite_Hashed_Maps
            (Key_Type => String,
             Element_Type => Enumeration,
             Hash => Ada.Strings.Hash,
             Equivalent_Keys => Standard."=");
             
        type Map is new Maps.Map with null record;
        
        type Option(Valid : Boolean := False) is record
            case Valid is
                when False => null;
                when True => Value : Enumeration := Enumeration'First;
            end case;
        end record;
        
        overriding 
        function Contains(Self : Map; Key : String) return Boolean;
        function Find(Self : Map; Key : String) return Option;
        
        function Make return Map;
        
        function "&"(L : Map; R : Enumeration) return Map;
        
        Empty_Map : constant Map := (Maps.Empty_Map with null record);
             
    end Enumeration_Search;

```

body file

```ada
    package body Enumeration_Search is

        function Contains(Self : Map; Key : String) return Boolean is
            use Ada.Characters.Handling;
        begin
            return Maps.Map(Self).Contains(To_Upper(Key));
        end Contains;
        
        function Find(Self : Map; Key : String) return Option is
            use Ada.Characters.Handling;
            Location : constant Maps.Cursor := Self.Find(To_Upper(Key));
            
            use type Maps.Cursor;
        begin
            if Location = Maps.No_Element then
                return (Valid => False);
            else
                return (Valid => True, Value => Self(Location));
            end if;
        end Find;
        
        function Make return Map is
        begin
            return Result : Map do
                for Value in Enumeration'Range loop
                    Result.Insert
                    (Key => Value'Image,
                     New_Item => Value);
                end loop;
            end return;
        end Make;
        
        function "&"(L : Map; R : Enumeration) return Map is
        begin
            return Result : Map := L do
                Result.Insert
                    (Key => R'Image,
                     New_Item => R);
            end return;
        end "&";
        
    end Enumeration_Search;

```

example:

```ada
    type My_Type is (Abc, Def, Ghi);
    
    package My_Type_Search is new Enumeration_Search(My_Type);
    use type My_Type_Search.Map;

    Full_Search : constant My_Type_Search.Map := My_Type_Search.Make;
    
    Constrained_Search : constant My_Type_Search.Map := My_Type_Search.Empty_Map
        & Abc 
        & Ghi;

```

---

<div class="post-metadata">

### Author: ![Verisimilitude](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/verisimilitude/32/384_2.png) [@Verisimilitude](https://forum.ada-lang.io/u/Verisimilitude)
#### Post date: [March 3, 2024, 11:36pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/5 "2024-03-03T23:36:20Z")

</div>

Something like that didn’t even occur to me. It seems a little heavyweight for something like this, but if he’s willing to do something like that, he could always use a trie for the mapping. I have a library he can use, if he’d be interested.

---

<div class="post-metadata">

### Author: ![JC001](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/j/e56c9b/32.png) [@JC001](https://forum.ada-lang.io/u/JC001)
#### Post date: [March 4, 2024, 10:06am UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/6 "2024-03-04T10:06:59Z")

</div>

```ada
(for some E in Some_Enum => E'Image = To_Upper (Potential_Value) )

```

---

<div class="post-metadata">

### Author: ![mosteo](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/mosteo/32/8_2.png) [@mosteo](https://forum.ada-lang.io/u/mosteo)
#### Post date: [March 6, 2024, 9:01am UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/7 "2024-03-06T09:01:57Z")

</div>

Thanks for all the comments, people, and the creativity, but I was hoping there was some simple, ARM-intended way, such a `'Valid` attribute that took a string, that I had overlooked.

---

<div class="post-metadata">

### Author: ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)
#### Post date: [March 6, 2024, 2:43pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/8 "2024-03-06T14:43:07Z")

</div>

I think the ARM more often than not tends to go the way of exception propagation for more things than I prefer (but I primarily code in bare metal contexts, so exceptions are less useful to me).

---

<div class="post-metadata">

### Author: ![sttaft](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/sttaft/32/12_2.png) [@sttaft](https://forum.ada-lang.io/u/sttaft)
#### Post date: [June 25, 2024, 7:43am UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/9 "2024-06-25T07:43:56Z")

</div>

Arnaud Charlet points out that GNAT has a 'Valid\_Value attribute function that does what you want:

[https://docs.adacore.com/gnat\_rm-docs/html/gnat\_rm/gnat\_rm/implementation\_defined\_attributes.html#attribute-valid-value](https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/implementation_defined_attributes.html#attribute-valid-value)

---

<div class="post-metadata">

### Author: ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)
#### Post date: [August 26, 2024, 3:50pm UTC](https://forum.ada-lang.io/t/checking-validity-of-enum-value-image-without-exception/695/10 "2024-08-26T15:50:50Z")

</div>

> [@Lucretia](#):
>
> This is one area where an option type would be handy.

I keep telling people, you can use unconstrained arrays for this…

> [@mosteo](#):
>
> Just double checking: is there any way to ascertain that a string can be converted to an enumeration value that does not involve raising an exception,
> 
> I don’t think so as `'Valid` takes a variable of the type, but I might be missing something?

Let me show you how:

```ada
Generic
   Type Element is (<>);
Package Generic_Optional is
   Subtype Index is Boolean range True..True;
   Type Optional is Array(Index range <>) of Element;

   Function From_String( Object: String ) return Optional;
End Generic_Optional;

Package Body Generic_Optional is
   Function From_String( Object: String ) return Optional is
   Begin
      Return Optional'( True => Some_Enum'Value (Object) );
   Exception
      Return Optional'( True..False => <> ); -- Null array
   End From_String;
End Generic_Optional;

```

Granted, you can’t use this technique on unconstrained elements; but otherwise it does confer a **big** advantage: considering _optional_ as an unconstrained array of 0 or 1 elements guides you to using for-loops on arrays for the processing, allowing you to use other unconstrained arrays [0…N] within the system w/o a [major] rewrite.
