Source

fantomongo / fan / ObjectID.fan

Liam Staskawicz 2282ec2 
















Liam Staskawicz 2d0737e 

Liam Staskawicz 870ac9d 
Liam Staskawicz 2d0737e 



katox 1fb5c5c 
Liam Staskawicz 2d0737e 


Liam Staskawicz 870ac9d 
Liam Staskawicz 2d0737e 





Liam Staskawicz 870ac9d 
Liam Staskawicz 0b1f1d6 

Liam Staskawicz 2d0737e 
katox 1fb5c5c 






Liam Staskawicz 2d0737e 


Liam Staskawicz 0b1f1d6 


Liam Staskawicz 2d0737e 

katox 1fb5c5c 



Liam Staskawicz 2d0737e 
katox 1fb5c5c 







Liam Staskawicz 2d0737e 












Liam Staskawicz 870ac9d 
Liam Staskawicz 2d0737e 






Dariusz Luksza 81fdad2 



Liam Staskawicz 2d0737e 






Liam Staskawicz 870ac9d 
Liam Staskawicz 2d0737e 




Liam Staskawicz 870ac9d 




Liam Staskawicz 2d0737e 







////////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2010 Liam Staskawicz
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

using inet
using concurrent

**
**  ObjectID
**
@Serializable { simple = true }
const class ObjectID 
{
  static const Int SIZE := 12
  private static const AtomicInt counter := AtomicInt(0)
  private const Int inc
  private const Int time
  private const Int machine
  
  new make()
  { 
    this.inc = counter.incrementAndGet().and(0xFFFFFFFF)
    this.time = DateTime.nowUnique.and(0xFFFFFFFF)
    this.machine = IpAddr.local.bytes.toDigest("MD5").readS4.and(0xFFFFFFFF)
  }

  new makeAll(Int inc, Int time, Int machine)
  { 
    this.inc = inc
    this.time = time
    this.machine = machine
  }
  
  new fromStream(InStream ins)
  {
    this.time = ins.readS4.and(0xFFFFFFFF)
    this.machine = ins.readS4.and(0xFFFFFFFF)
    this.inc = ins.readS4.and(0xFFFFFFFF)
  }
  
  ** Parse ObjectID from according to the string format defined in mongodb documentation
  ** If invalid format and checked is false
  ** return null, otherwise throw Err.
  static new fromStr(Str s, Bool checked := true)
  {
    if (!isValid(s)) {
      if (checked)
        throw Err("invalid ObjectID format")
      return null
    }
    return makeAll(s[16..23].toInt(16).and(0xFFFFFFFF),
                   s[0..7].toInt(16).and(0xFFFFFFFF),
                   s[8..15].toInt(16).and(0xFFFFFFFF))
  }
  
  override Str toStr()
  {
    s := StrBuf()
    [time, machine, inc].each |val, i| {
      s.add(val.toHex(8))
    }
    return s.toStr()
  }
  
  override Bool equals(Obj? o)
  {
    if (o isnot ObjectID)
      return false
    
    return ((o as ObjectID).inc == this.inc && 
            (o as ObjectID).machine == this.machine && 
            (o as ObjectID).time == this.time)
  }
  
  override Int hash() {
    return 31 * (inc.hash.xor(machine.hash) + time.hash)
  }
  
  OutStream write(OutStream o)
  {
    return o.writeI4(time).writeI4(machine).writeI4(inc)
  }
  
  static Bool isValid(Str s)
  {
    if (s.size != 24)
      return false;
    
    // make sure it's all hex digits so we can convert to Ints
    valid := true
    s.each |Int c| {
      if (c >= '0' && c <= '9')
        return                 
      if (c >= 'a' && c <= 'f')
        return                 
      if (c >= 'A' && c <= 'F')
        return
      valid = false
    }
    return valid
  }
  
}