ext2: Factor inode-group deserialization out
diff --git a/src/filo-fs-ext2.adb b/src/filo-fs-ext2.adb
index d7ee599..a69730e 100644
--- a/src/filo-fs-ext2.adb
+++ b/src/filo-fs-ext2.adb
@@ -118,22 +118,22 @@
             declare
                S_Desc_Size : constant Unsigned_16 := Read_LE16 (Super_Block, 63 * 4 + 2);
             begin
-               if Natural (S_Desc_Size) in Desc_Size and
+               if Natural (S_Desc_Size) in Group_Desc_Size and
                   Natural (S_Desc_Size) <= Static.Block_Size and
                   Is_Power_Of_2 (S_Desc_Size)
                then
-                  Static.Desc_Size := Desc_Size (S_Desc_Size);
+                  Static.Group_Desc_Size := Group_Desc_Size (S_Desc_Size);
                else
                   Success := False;
                   return;
                end if;
-               pragma Assert (Static.Block_Size / Static.Desc_Size <= Natural (Group_In_Block_Count'Last));
+               pragma Assert (Static.Block_Size / Static.Group_Desc_Size <= Natural (Group_In_Block_Count'Last));
             end;
-            Static.Feature_64Bit := Static.Feature_64Bit and Static.Desc_Size >= 64;
+            Static.Feature_64Bit := Static.Feature_64Bit and Static.Group_Desc_Size >= 64;
          else
-            Static.Desc_Size := Desc_Size'First;
+            Static.Group_Desc_Size := Group_Desc_Size'First;
          end if;
-         Static.Desc_Per_Block := Group_In_Block_Count (Static.Block_Size / Static.Desc_Size);
+         Static.Group_Desc_Per_Block := Group_In_Block_Count (Static.Block_Size / Static.Group_Desc_Size);
       end;
       pragma Assert_And_Cut (Success);
 
@@ -606,6 +606,34 @@
       end if;
    end Extent_Block_Map;
 
+   procedure Parse_Group
+     (Static      : in     Mount_State;
+      Table_Start :    out FSBlock_Offset;
+      Buf         : in     Buffer_Type;
+      Success     :    out Boolean)
+   with
+      Pre =>
+         Buf'Length >= Group_Desc_Size'First and
+         (if Static.Feature_64Bit then Buf'Length >= 64)
+   is
+      Inode_Table_Block : constant Unsigned_64 :=
+         (if Static.Feature_64Bit
+          then Shift_Left (Unsigned_64 (Read_LE32 (Buf, 40)), 32)
+          else 0)
+         or
+         Unsigned_64 (Read_LE32 (Buf, 8));
+   begin
+         if Inode_Table_Block >= Unsigned_64 (Static.First_Data_Block) and
+            Inode_Table_Block <= Unsigned_64 (FSBlock_Offset'Last)
+         then
+            Table_Start := FSBlock_Offset (Inode_Table_Block);
+            Success := True;
+         else
+            Table_Start := 0;
+            Success := False;
+         end if;
+   end Parse_Group;
+
    procedure Parse_Inode
      (Static   : in     Mount_State;
       Inode    : in out Inode_Info;
@@ -669,34 +697,20 @@
       Static : Mount_State renames State.Static;
       Cache : Cache_Buffer renames State.Cache.Buffer;
 
-      ------------------------
-      -- Group deserialization
-
-      subtype Group_Off is Natural range 0 .. Desc_Size'Last;
-      function Group_Byte_Offset (Idx : Desc_In_Block_Index; Off : Group_Off) return Natural
-      is
-         (Natural (Idx) * Static.Desc_Size + Off);
-
-      function Group_Inode_Table (Buf : Buffer_Type; Idx : Desc_In_Block_Index) return Unsigned_64
-      is
-        ((if Static.Feature_64Bit
-          then Shift_Left (Unsigned_64 (Read_LE32 (Buf, Group_Byte_Offset (Idx, 40))), 32)
-          else 0)
-         or
-         Unsigned_64 (Read_LE32 (Buf, Group_Byte_Offset (Idx, 8))))
-      with
-         Pre => Buf'Length >= Group_Byte_Offset (Idx, (if Static.Feature_64Bit then 44 else 12));
-
       Group : constant Group_Index := Group_Index ((Inode - 1) / Static.Inodes_Per_Group);
-      Desc_Block : constant FSBlock_Offset :=
-         1 + FSBlock_Offset (Static.First_Data_Block) + FSBlock_Offset (Group / Static.Desc_Per_Block);
+      Group_Block : constant FSBlock_Offset :=
+         1 + FSBlock_Offset (Static.First_Data_Block) + FSBlock_Offset (Group / Static.Group_Desc_Per_Block);
+      Group_In_Block : constant Group_In_Block_Index := Group_In_Block_Index (Group mod Static.Group_Desc_Per_Block);
+      Group_In_Block_Offset : constant Natural := Natural (Group_In_Block) * Static.Group_Desc_Size;
+
       Cache_Start, Cache_End : Max_Block_Index;
+      First_Table_Block : FSBlock_Offset;
    begin
       Cache_FSBlock
         (Static      => Static,
          Cache       => State.Cache,
-         Phys        => Desc_Block,
-         Level       => Natural (Group_Index'Min (Group / Static.Desc_Per_Block,
+         Phys        => Group_Block,
+         Level       => Natural (Group_Index'Min (Group / Static.Group_Desc_Per_Block,
                                                    Group_Index (Block_Cache_Index'Last))),
          Cache_Start => Cache_Start,
          Cache_End   => Cache_End,
@@ -706,31 +720,37 @@
       end if;
       pragma Assert_And_Cut (Cache_End = Cache_Start + Static.Block_Size - 1);
 
+      Parse_Group
+        (Static      => Static,
+         Table_Start => First_Table_Block,
+         Buf         => Cache (Cache_Start + Group_In_Block_Offset ..
+                                 Cache_Start + Group_In_Block_Offset + Static.Group_Desc_Size - 1),
+         Success     => Success);
+      if not Success then
+         return;
+      end if;
+      pragma Assert_And_Cut (Boolean'(True));
+
       declare
-         Desc : constant Desc_In_Block_Index := Desc_In_Block_Index (Group mod Static.Desc_Per_Block);
          Inode_In_Group : constant Inode_In_Group_Index :=
             Inode_In_Group_Index ((Inode - 1) mod Static.Inodes_Per_Group);
-         First_Table_Block : constant Unsigned_64 := Group_Inode_Table (Cache (Cache_Start .. Cache_End), Desc);
-         Block_Offset : constant Unsigned_64 := Unsigned_64 (Inode_In_Group / Static.Inodes_Per_Block);
 
+         Inode_Block : constant FSBlock_Offset := FSBlock_Offset (Inode_In_Group / Static.Inodes_Per_Block);
          Inode_In_Block : constant Inode_In_Block_Index :=
             Inode_In_Block_Index (Inode_In_Group mod Static.Inodes_Per_Block);
          Inode_In_Block_Offset : constant Natural :=
             Natural (Inode_In_Block) * Static.Inode_Size;
       begin
-         if First_Table_Block < Unsigned_64 (Static.First_Data_Block) or
-            First_Table_Block > Unsigned_64 (FSBlock_Offset'Last) - Block_Offset
-         then
+         if First_Table_Block > FSBlock_Offset'Last - Inode_Block then
             Success := False;
             return;
          end if;
-         pragma Assert_And_Cut
-           (First_Table_Block + Block_Offset in 0 .. Unsigned_64 (FSBlock_Offset'Last));
+         pragma Assert_And_Cut (First_Table_Block + Inode_Block in FSBlock_Offset);
 
          Cache_FSBlock
            (Static      => Static,
             Cache       => State.Cache,
-            Phys        => FSBlock_Offset (First_Table_Block + Block_Offset),
+            Phys        => FSBlock_Offset (First_Table_Block + Inode_Block),
             Level       => Block_Cache_Index'Last,
             Cache_Start => Cache_Start,
             Cache_End   => Cache_End,
diff --git a/src/filo-fs-ext2.ads b/src/filo-fs-ext2.ads
index 6003198..5e6b641 100644
--- a/src/filo-fs-ext2.ads
+++ b/src/filo-fs-ext2.ads
@@ -74,7 +74,7 @@
    type Inode_0_Index is new Unsigned_32;
    subtype Inode_Index is Inode_0_Index range 2 .. Inode_0_Index'Last;
    subtype Inode_Size is Positive range 128 .. Positive (Unsigned_16'Last);
-   subtype Desc_Size  is Positive range  32 .. 2 ** 15; -- power-of-2 that fits in 16 bits
+   subtype Group_Desc_Size  is Positive range  32 .. 2 ** 15; -- power-of-2 that fits in 16 bits
 
    type Inode_Type is (Dir, Regular, Link, Fast_Link);
    type Inode_Length is range 0 .. 2 ** 46;
@@ -89,8 +89,8 @@
 
    type Group_Index is new Inode_0_Index;
    subtype Group_In_Block_Count is Group_Index
-      range 1 .. Group_Index (Block_Size'Last / Desc_Size'First);
-   type Desc_In_Block_Index is new Natural range 0 .. Natural (Group_In_Block_Count'Last - 1);
+      range 1 .. Group_Index (Block_Size'Last / Group_Desc_Size'First);
+   type Group_In_Block_Index is new Natural range 0 .. Natural (Group_In_Block_Count'Last - 1);
 
    subtype Inode_In_Group_Count is Inode_0_Index range 1 .. Inode_0_Index'Last;
    type Inode_In_Group_Index is new Inode_0_Index range 0 .. Inode_In_Group_Count'Last - 1;
@@ -106,8 +106,8 @@
       Inodes_Per_Group     : Inode_In_Group_Count := Inode_In_Group_Count'First;
       Inode_Size           : Ext2.Inode_Size := Ext2.Inode_Size'First;
       Inodes_Per_Block     : Inode_In_Block_Count := Inode_In_Block_Count'First;
-      Desc_Size            : Ext2.Desc_Size := Ext2.Desc_Size'First;
-      Desc_Per_Block       : Group_In_Block_Count := Group_In_Block_Count'First;
+      Group_Desc_Size      : Ext2.Group_Desc_Size := Ext2.Group_Desc_Size'First;
+      Group_Desc_Per_Block : Group_In_Block_Count := Group_In_Block_Count'First;
       Feature_Extents      : Boolean := False;
       Feature_64Bit        : Boolean := False;
    end record;