spreadsheetx 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
 - data/lib/spreadsheetx.rb +1 -0
 - data/lib/spreadsheetx/cell_format.rb +19 -0
 - data/lib/spreadsheetx/workbook.rb +22 -0
 - data/lib/spreadsheetx/worksheet.rb +46 -16
 - data/spec/spreadsheetx_spec.rb +30 -1
 - data/spreadsheetx.gemspec +2 -1
 - data/templates/spec.xlsx +0 -0
 - metadata +3 -2
 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0.2. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.2.1
         
     | 
    
        data/lib/spreadsheetx.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SpreadsheetX
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              # this object represents an existing cell format in the workbook
         
     | 
| 
      
 4 
     | 
    
         
            +
              class CellFormat
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :id
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :format
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(id, format)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @id = id
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @format = format
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
                
         
     | 
| 
      
 14 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 15 
     | 
    
         
            +
                  id.to_s
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
                
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,6 +5,7 @@ module SpreadsheetX 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
                attr_reader :path
         
     | 
| 
       7 
7 
     | 
    
         
             
                attr_reader :worksheets
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :formats
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
                # return a Workbook object which relates to an existing xlsx file on disk
         
     | 
| 
       10 
11 
     | 
    
         
             
                def initialize(path)
         
     | 
| 
         @@ -33,6 +34,26 @@ module SpreadsheetX 
     | 
|
| 
       33 
34 
     | 
    
         | 
| 
       34 
35 
     | 
    
         
             
                    end
         
     | 
| 
       35 
36 
     | 
    
         | 
| 
      
 37 
     | 
    
         
            +
                    # open the styles, to get the cell formats
         
     | 
| 
      
 38 
     | 
    
         
            +
                    archive.fopen('xl/styles.xml') do |f| 
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                      # read contents of this file
         
     | 
| 
      
 41 
     | 
    
         
            +
                      file_contents = f.read 
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                      #parse the XML and build the worksheets
         
     | 
| 
      
 44 
     | 
    
         
            +
                      @formats = []
         
     | 
| 
      
 45 
     | 
    
         
            +
                      # parse the XML and hold the doc
         
     | 
| 
      
 46 
     | 
    
         
            +
                      xml_doc = XML::Document.string(file_contents)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      # set the default namespace
         
     | 
| 
      
 48 
     | 
    
         
            +
                      xml_doc.root.namespaces.default_prefix = 'spreadsheetml'
         
     | 
| 
      
 49 
     | 
    
         
            +
                      
         
     | 
| 
      
 50 
     | 
    
         
            +
                      format_id = 0
         
     | 
| 
      
 51 
     | 
    
         
            +
                      xml_doc.find('spreadsheetml:numFmts/spreadsheetml:numFmt').each do |node|
         
     | 
| 
      
 52 
     | 
    
         
            +
                        @formats.push SpreadsheetX::CellFormat.new((format_id+=1), node['formatCode'])
         
     | 
| 
      
 53 
     | 
    
         
            +
                      end
         
     | 
| 
      
 54 
     | 
    
         
            +
                      
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
                    
         
     | 
| 
       36 
57 
     | 
    
         
             
                  end
         
     | 
| 
       37 
58 
     | 
    
         
             
                end
         
     | 
| 
       38 
59 
     | 
    
         | 
| 
         @@ -54,6 +75,7 @@ module SpreadsheetX 
     | 
|
| 
       54 
75 
     | 
    
         | 
| 
       55 
76 
     | 
    
         
             
                end
         
     | 
| 
       56 
77 
     | 
    
         | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
       57 
79 
     | 
    
         
             
              end
         
     | 
| 
       58 
80 
     | 
    
         | 
| 
       59 
81 
     | 
    
         
             
            end
         
     | 
| 
         @@ -28,19 +28,37 @@ module SpreadsheetX 
     | 
|
| 
       28 
28 
     | 
    
         
             
                end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                # update the value of a particular cell, if the row or cell doesnt exist in the XML, then it will be created
         
     | 
| 
       31 
     | 
    
         
            -
                def update_cell(col_number, row_number, val)
         
     | 
| 
      
 31 
     | 
    
         
            +
                def update_cell(col_number, row_number, val, format=nil)
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                  cell_id = SpreadsheetX::Worksheet.cell_id(col_number, row_number)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  val_is_a_date = (val.kind_of?(Date) || val.kind_of?(Time) || val.kind_of?(DateTime))
         
     | 
| 
      
 36 
     | 
    
         
            +
                  
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # if the val is nil or an empty string, then just delete the cell
         
     | 
| 
      
 38 
     | 
    
         
            +
                  if val.nil? || val == ''
         
     | 
| 
      
 39 
     | 
    
         
            +
                    if cell = @xml_doc.find_first("spreadsheetml:sheetData/spreadsheetml:row[@r=#{row_number}]/spreadsheetml:c[@r='#{cell_id}']")
         
     | 
| 
      
 40 
     | 
    
         
            +
                      cell.remove!
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
                    return
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
       34 
44 
     | 
    
         | 
| 
       35 
45 
     | 
    
         
             
                  row = @xml_doc.find_first("spreadsheetml:sheetData/spreadsheetml:row[@r=#{row_number}]")
         
     | 
| 
       36 
46 
     | 
    
         | 
| 
       37 
47 
     | 
    
         
             
                  # was this row found
         
     | 
| 
       38 
48 
     | 
    
         
             
                  unless row
         
     | 
| 
      
 49 
     | 
    
         
            +
                    
         
     | 
| 
       39 
50 
     | 
    
         
             
                    # build a new row
         
     | 
| 
       40 
51 
     | 
    
         
             
                    row = XML::Node.new('row')
         
     | 
| 
       41 
52 
     | 
    
         
             
                    row['r'] = row_number.to_s
         
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
      
 53 
     | 
    
         
            +
                    
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # if there are no rows higher than this one, then add this row to the end of the sheetData
         
     | 
| 
      
 55 
     | 
    
         
            +
                    next_largest = @xml_doc.find_first("spreadsheetml:sheetData/spreadsheetml:row[@r>#{row_number}]")
         
     | 
| 
      
 56 
     | 
    
         
            +
                    if next_largest
         
     | 
| 
      
 57 
     | 
    
         
            +
                      next_largest.prev = row
         
     | 
| 
      
 58 
     | 
    
         
            +
                    else  # there are no rows higher than this one
         
     | 
| 
      
 59 
     | 
    
         
            +
                      # add this row to the end of the sheetData
         
     | 
| 
      
 60 
     | 
    
         
            +
                      @xml_doc.find_first('spreadsheetml:sheetData') << row
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
       44 
62 
     | 
    
         
             
                  end
         
     | 
| 
       45 
63 
     | 
    
         | 
| 
       46 
64 
     | 
    
         
             
                  cell = row.find_first("spreadsheetml:c[@r='#{cell_id}']")
         
     | 
| 
         @@ -49,30 +67,42 @@ module SpreadsheetX 
     | 
|
| 
       49 
67 
     | 
    
         
             
                    # build a new cell
         
     | 
| 
       50 
68 
     | 
    
         
             
                    cell = XML::Node.new('c')
         
     | 
| 
       51 
69 
     | 
    
         
             
                    cell['r'] = cell_id
         
     | 
| 
       52 
     | 
    
         
            -
                    # add it to the other  
     | 
| 
      
 70 
     | 
    
         
            +
                    # add it to the other cells in this row
         
     | 
| 
       53 
71 
     | 
    
         
             
                    row << cell
         
     | 
| 
       54 
72 
     | 
    
         
             
                  end
         
     | 
| 
       55 
73 
     | 
    
         | 
| 
      
 74 
     | 
    
         
            +
                  # are we setting a format
         
     | 
| 
      
 75 
     | 
    
         
            +
                  cell['s'] = format.to_s
         
     | 
| 
      
 76 
     | 
    
         
            +
                  
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # reset this attribute
         
     | 
| 
      
 78 
     | 
    
         
            +
                  cell['t'] = ''
         
     | 
| 
      
 79 
     | 
    
         
            +
                  
         
     | 
| 
       56 
80 
     | 
    
         
             
                  # create the node which represents the value in the cell
         
     | 
| 
       57 
     | 
    
         
            -
                   
     | 
| 
      
 81 
     | 
    
         
            +
                  
         
     | 
| 
      
 82 
     | 
    
         
            +
                  # numeric types
         
     | 
| 
      
 83 
     | 
    
         
            +
                  if val.kind_of?(Integer) || val.kind_of?(Float) || val.kind_of?(Fixnum)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    
         
     | 
| 
      
 85 
     | 
    
         
            +
                    cell_value = XML::Node.new('v')
         
     | 
| 
      
 86 
     | 
    
         
            +
                    cell_value.content = val.to_s
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  # if we are using a format, then dates are stored as floats, otherwise they get caught by string use a string
         
     | 
| 
      
 89 
     | 
    
         
            +
                  elsif format && val_is_a_date
         
     | 
| 
       58 
90 
     | 
    
         | 
| 
      
 91 
     | 
    
         
            +
                    cell_value = XML::Node.new('v')
         
     | 
| 
      
 92 
     | 
    
         
            +
                    # dates are stored as flaots, otherwise use a string
         
     | 
| 
      
 93 
     | 
    
         
            +
                    cell_value.content = (val.to_time.to_f / (60*60*24)).to_s
         
     | 
| 
      
 94 
     | 
    
         
            +
                    
         
     | 
| 
      
 95 
     | 
    
         
            +
                  else # assume its a string
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
       59 
97 
     | 
    
         
             
                    # put the strings inline to make life easier
         
     | 
| 
       60 
98 
     | 
    
         
             
                    cell['t'] = 'inlineStr'
         
     | 
| 
       61 
99 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                    # the string node  
     | 
| 
      
 100 
     | 
    
         
            +
                    # the string node looks like <is><t>string</t></is>
         
     | 
| 
       63 
101 
     | 
    
         
             
                    is = XML::Node.new('is')
         
     | 
| 
       64 
102 
     | 
    
         
             
                    t = XML::Node.new('t')
         
     | 
| 
       65 
     | 
    
         
            -
                    t.content = val
         
     | 
| 
      
 103 
     | 
    
         
            +
                    t.content = val_is_a_date ? val.to_time.strftime('%Y-%m-%d %H:%M:%S') : val.to_s
         
     | 
| 
       66 
104 
     | 
    
         | 
| 
       67 
105 
     | 
    
         
             
                    cell_value = ( is << t )
         
     | 
| 
       68 
     | 
    
         
            -
                    
         
     | 
| 
       69 
     | 
    
         
            -
                  else
         
     | 
| 
       70 
     | 
    
         
            -
                    
         
     | 
| 
       71 
     | 
    
         
            -
                    # incase this was an inline string, clear out this attribute
         
     | 
| 
       72 
     | 
    
         
            -
                    cell['t'] = ''
         
     | 
| 
       73 
     | 
    
         
            -
                    
         
     | 
| 
       74 
     | 
    
         
            -
                    cell_value = XML::Node.new('v')
         
     | 
| 
       75 
     | 
    
         
            -
                    cell_value.content = val.to_s
         
     | 
| 
       76 
106 
     | 
    
         | 
| 
       77 
107 
     | 
    
         
             
                  end
         
     | 
| 
       78 
108 
     | 
    
         | 
| 
         @@ -94,7 +124,7 @@ module SpreadsheetX 
     | 
|
| 
       94 
124 
     | 
    
         | 
| 
       95 
125 
     | 
    
         
             
                # returns the xml representation of this worksheet
         
     | 
| 
       96 
126 
     | 
    
         
             
                def to_s
         
     | 
| 
       97 
     | 
    
         
            -
                  @xml_doc.to_s
         
     | 
| 
      
 127 
     | 
    
         
            +
                  @xml_doc.to_s(:indent => false).gsub(/\n/,"\r\n")
         
     | 
| 
       98 
128 
     | 
    
         
             
                end
         
     | 
| 
       99 
129 
     | 
    
         | 
| 
       100 
130 
     | 
    
         
             
                # turns a cell address into its excel name, 1,1 = A1  2,3 = C2 etc.
         
     | 
    
        data/spec/spreadsheetx_spec.rb
    CHANGED
    
    | 
         @@ -27,7 +27,7 @@ describe "Spreadsheetx" do 
     | 
|
| 
       27 
27 
     | 
    
         
             
                empty_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec.xlsx"
         
     | 
| 
       28 
28 
     | 
    
         
             
                workbook = SpreadsheetX.open(empty_xlsx_file)
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                workbook.worksheets.last.row_count.should ==  
     | 
| 
      
 30 
     | 
    
         
            +
                workbook.worksheets.last.row_count.should == 8
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
              end
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
         @@ -107,6 +107,7 @@ describe "Spreadsheetx" do 
     | 
|
| 
       107 
107 
     | 
    
         
             
                workbook = SpreadsheetX.open(empty_xlsx_file)
         
     | 
| 
       108 
108 
     | 
    
         | 
| 
       109 
109 
     | 
    
         
             
                workbook.worksheets.last.update_cell(9, 9, Time.now)
         
     | 
| 
      
 110 
     | 
    
         
            +
                workbook.worksheets.last.update_cell(1, 4, 'A string')
         
     | 
| 
       110 
111 
     | 
    
         
             
                workbook.worksheets.last.update_cell(9, 10, 'A string')
         
     | 
| 
       111 
112 
     | 
    
         
             
                workbook.worksheets.last.update_cell(9, 11, 10.3)
         
     | 
| 
       112 
113 
     | 
    
         
             
                workbook.worksheets.last.update_cell(9, 12, 53)
         
     | 
| 
         @@ -116,7 +117,35 @@ describe "Spreadsheetx" do 
     | 
|
| 
       116 
117 
     | 
    
         
             
                workbook.save(new_xlsx_file)
         
     | 
| 
       117 
118 
     | 
    
         | 
| 
       118 
119 
     | 
    
         
             
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
              it "can read and return a list of number formats currently in the document" do
         
     | 
| 
      
 122 
     | 
    
         
            +
              
         
     | 
| 
      
 123 
     | 
    
         
            +
                # a valid xlsx file used for testing
         
     | 
| 
      
 124 
     | 
    
         
            +
                empty_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec.xlsx"
         
     | 
| 
      
 125 
     | 
    
         
            +
                workbook = SpreadsheetX.open(empty_xlsx_file)
         
     | 
| 
      
 126 
     | 
    
         
            +
              
         
     | 
| 
      
 127 
     | 
    
         
            +
                workbook.formats.count.should == 3
         
     | 
| 
      
 128 
     | 
    
         
            +
                workbook.formats.first.id.to_i.should > 0
         
     | 
| 
      
 129 
     | 
    
         
            +
                puts workbook.formats.first.format.should == '[$-F400]h:mm:ss\ AM/PM'
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                new_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec_various_content.xlsx"
         
     | 
| 
      
 132 
     | 
    
         
            +
                workbook.save(new_xlsx_file)
         
     | 
| 
      
 133 
     | 
    
         
            +
              
         
     | 
| 
      
 134 
     | 
    
         
            +
              end
         
     | 
| 
      
 135 
     | 
    
         
            +
              
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
              it "can set formats on cells" do
         
     | 
| 
      
 138 
     | 
    
         
            +
              
         
     | 
| 
      
 139 
     | 
    
         
            +
                # a valid xlsx file used for testing
         
     | 
| 
      
 140 
     | 
    
         
            +
                empty_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec.xlsx"
         
     | 
| 
      
 141 
     | 
    
         
            +
                workbook = SpreadsheetX.open(empty_xlsx_file)
         
     | 
| 
       119 
142 
     | 
    
         | 
| 
      
 143 
     | 
    
         
            +
                date_format = workbook.formats.first
         
     | 
| 
      
 144 
     | 
    
         
            +
                workbook.worksheets.last.update_cell(1, 8, Time.now, date_format)
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                new_xlsx_file = "#{File.dirname(__FILE__)}/../templates/spec_cell_format.xlsx"
         
     | 
| 
      
 147 
     | 
    
         
            +
                workbook.save(new_xlsx_file)
         
     | 
| 
       120 
148 
     | 
    
         | 
| 
      
 149 
     | 
    
         
            +
              end
         
     | 
| 
       121 
150 
     | 
    
         | 
| 
       122 
151 
     | 
    
         
             
            end
         
     | 
    
        data/spreadsheetx.gemspec
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            Gem::Specification.new do |s|
         
     | 
| 
       7 
7 
     | 
    
         
             
              s.name = %q{spreadsheetx}
         
     | 
| 
       8 
     | 
    
         
            -
              s.version = "0.2. 
     | 
| 
      
 8 
     | 
    
         
            +
              s.version = "0.2.1"
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         
     | 
| 
       11 
11 
     | 
    
         
             
              s.authors = ["Craig Ulliott"]
         
     | 
| 
         @@ -26,6 +26,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       26 
26 
     | 
    
         
             
                "Rakefile",
         
     | 
| 
       27 
27 
     | 
    
         
             
                "VERSION",
         
     | 
| 
       28 
28 
     | 
    
         
             
                "lib/spreadsheetx.rb",
         
     | 
| 
      
 29 
     | 
    
         
            +
                "lib/spreadsheetx/cell_format.rb",
         
     | 
| 
       29 
30 
     | 
    
         
             
                "lib/spreadsheetx/workbook.rb",
         
     | 
| 
       30 
31 
     | 
    
         
             
                "lib/spreadsheetx/worksheet.rb",
         
     | 
| 
       31 
32 
     | 
    
         
             
                "spec/spec_helper.rb",
         
     | 
    
        data/templates/spec.xlsx
    CHANGED
    
    | 
         Binary file 
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            name: spreadsheetx
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       4 
4 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       5 
     | 
    
         
            -
              version: 0.2. 
     | 
| 
      
 5 
     | 
    
         
            +
              version: 0.2.1
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors: 
         
     | 
| 
       8 
8 
     | 
    
         
             
            - Craig Ulliott
         
     | 
| 
         @@ -98,6 +98,7 @@ files: 
     | 
|
| 
       98 
98 
     | 
    
         
             
            - Rakefile
         
     | 
| 
       99 
99 
     | 
    
         
             
            - VERSION
         
     | 
| 
       100 
100 
     | 
    
         
             
            - lib/spreadsheetx.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib/spreadsheetx/cell_format.rb
         
     | 
| 
       101 
102 
     | 
    
         
             
            - lib/spreadsheetx/workbook.rb
         
     | 
| 
       102 
103 
     | 
    
         
             
            - lib/spreadsheetx/worksheet.rb
         
     | 
| 
       103 
104 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
         @@ -118,7 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       118 
119 
     | 
    
         
             
              requirements: 
         
     | 
| 
       119 
120 
     | 
    
         
             
              - - ">="
         
     | 
| 
       120 
121 
     | 
    
         
             
                - !ruby/object:Gem::Version 
         
     | 
| 
       121 
     | 
    
         
            -
                  hash:  
     | 
| 
      
 122 
     | 
    
         
            +
                  hash: 3923025067229430193
         
     | 
| 
       122 
123 
     | 
    
         
             
                  segments: 
         
     | 
| 
       123 
124 
     | 
    
         
             
                  - 0
         
     | 
| 
       124 
125 
     | 
    
         
             
                  version: "0"
         
     |