content: #!/usr/bin/python
  
  # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
  #
  # This source code is licensed under the MIT license found in the
  # LICENSE file in the root directory of this source tree.
  
  import errno
  import os
  import time
  
  import fbchisellldbbase as fb
  import fbchisellldbobjecthelpers as objectHelpers
  import lldb
  
  
  def lldbcommands():
      return [FBVisualizeCommand()]
  
  
  def _showImage(commandForImage):
      imageDirectory = "/tmp/xcode_debug_images/"
  
      imageName = time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime()) + ".png"
      imagePath = imageDirectory + imageName
  
      try:
          os.makedirs(imageDirectory)
      except OSError as e:
          if e.errno == errno.EEXIST and os.path.isdir(imageDirectory):
              pass
          else:
              raise
  
      toPNG = "(id)UIImagePNGRepresentation((id){})".format(commandForImage)
      imageDataAddress = fb.evaluateExpressionValue(toPNG, tryAllThreads=True).GetValue()
      imageBytesStartAddress = fb.evaluateExpression(
          "(void *)[(id)" + imageDataAddress + " bytes]"
      )
      imageBytesLength = fb.evaluateExpression(
          "(NSUInteger)[(id)" + imageDataAddress + " length]"
      )
  
      address = int(imageBytesStartAddress, 16)
      length = int(imageBytesLength)
  
      if not (address or length):
          print("Could not get image data.")
          return
  
      process = lldb.debugger.GetSelectedTarget().GetProcess()
      error = lldb.SBError()
      mem = process.ReadMemory(address, length, error)
  
      if error is not None and str(error) != "success":
          print(error)
      else:
          with open(imagePath, "wb") as imgFile:
              imgFile.write(mem)
          os.system("open " + imagePath)
  
  
  def _colorIsCGColorRef(color):
      color = "(CGColorRef)(" + color + ")"
  
      result = fb.evaluateExpressionValue(
          "(unsigned long)CFGetTypeID({color}) == (unsigned long)CGColorGetTypeID()".format(
              color=color
          )
      )
  
      if result.GetError() is not None and str(result.GetError()) != "success":
          print("got error: {}".format(result))
          return False
      else:
          isCFColor = result.GetValueAsUnsigned() != 0
          return isCFColor
  
  
  def _showColor(color):
      color = "(" + color + ")"
  
      colorToUse = color
      isCF = _colorIsCGColorRef(color)
      if isCF:
          colorToUse = "[[UIColor alloc] initWithCGColor:(CGColorRef){}]".format(color)
      else:
          isCI = objectHelpers.isKindOfClass(color, "CIColor")
          if isCI:
              colorToUse = "[UIColor colorWithCIColor:(CIColor *){}]".format(color)
  
      imageSize = 58
      fb.evaluateEffect(
          "UIGraphicsBeginImageContextWithOptions((CGSize)CGSizeMake({imageSize}, {imageSize}), NO, 0.0)".format(
              imageSize=imageSize
          )
      )
      fb.evaluateEffect("[(id){} setFill]".format(colorToUse))
      fb.evaluateEffect(
          "UIRectFill((CGRect)CGRectMake(0.0, 0.0, {imageSize}, {imageSize}))".format(
              imageSize=imageSize
          )
      )
  
      result = fb.evaluateExpressionValue(
          "(UIImage *)UIGraphicsGetImageFromCurrentImageContext()"
      )
      if result.GetError() is not None and str(result.GetError()) != "success":
          print("got error {}".format(result))
          print(result.GetError())
      else:
          image = result.GetValue()
          _showImage(image)
  
      fb.evaluateEffect("UIGraphicsEndImageContext()")
  
  
  def _showLayer(layer):
      layer = "(" + layer + ")"
      size = "((CGRect)[(id)" + layer + " bounds]).size"
  
      width = float(fb.evaluateExpression("(CGFloat)(" + size + ".width)"))
      height = float(fb.evaluateExpression("(CGFloat)(" + size + ".height)"))
      if width == 0.0 or height == 0.0:
          print(
              "Nothing to see here - the size of this element is {} x {}.".format(
                  width, height
              )
          )
          return
  
      fb.evaluateEffect("UIGraphicsBeginImageContextWithOptions(" + size + ", NO, 0.0)")
      fb.evaluateEffect(
          "[(id)" + layer + " renderInContext:(void *)UIGraphicsGetCurrentContext()]"
      )
  
      result = fb.evaluateExpressionValue(
          "(UIImage *)UIGraphicsGetImageFromCurrentImageContext()"
      )
      if result.GetError() is not None and str(result.GetError()) != "success":
          print(result.GetError())
      else:
          image = result.GetValue()
          _showImage(image)
  
      fb.evaluateEffect("UIGraphicsEndImageContext()")
  
  
  def _showPixelBuffer(target):
      imgVar = "$imageOut" + str(round(time.time()))
      fb.evaluateExpression("CGImageRef " + imgVar + " = NULL")
      fb.evaluateExpression(
          "(OSStatus)VTCreateCGImageFromCVPixelBuffer((CVPixelBufferRef)"
          + target
          + ", NULL, &"
          + imgVar
          + ")"
      )
      image = fb.evaluateExpression("[UIImage imageWithCGImage:" + imgVar + "]")
      _showImage(image)
      fb.evaluateExpression("CGImageRelease(" + imgVar + ")")
  
  
  def _dataIsImage(data):
      data = "(" + data + ")"
  
      result = fb.evaluateExpressionValue("(id)[UIImage imageWithData:" + data + "]")
  
      if result.GetError() is not None and str(result.GetError()) != "success":
          return False
      else:
          isImage = result.GetValueAsUnsigned() != 0
          return isImage
  
  
  def _dataIsString(data):
      data = "(" + data + ")"
  
      result = fb.evaluateExpressionValue(
          "(NSString*)[[NSString alloc] initWithData:" + data + " encoding:4]"
      )
  
      if result.GetError() is not None and str(result.GetError()) != "success":
          return False
      else:
          isString = result.GetValueAsUnsigned() != 0
          return isString
  
  
  def _visualize(target):
      target = fb.evaluateInputExpression(target)
  
      if fb.evaluateBooleanExpression(
          "(unsigned long)CFGetTypeID((CFTypeRef)"
          + target
          + ") == (unsigned long)CGImageGetTypeID()"
      ):
          _showImage("(id)[UIImage imageWithCGImage:" + target + "]")
      elif fb.evaluateBooleanExpression(
          "(unsigned long)CFGetTypeID((CFTypeRef)"
          + target
          + ") == (unsigned long)CVPixelBufferGetTypeID()"
      ):
          _showPixelBuffer(target)
      else:
          if objectHelpers.isKindOfClass(target, "UIImage"):
              _showImage(target)
          elif objectHelpers.isKindOfClass(target, "UIView"):
              _showLayer("[(id)" + target + " layer]")
          elif objectHelpers.isKindOfClass(target, "CALayer"):
              _showLayer(target)
          elif (
              objectHelpers.isKindOfClass(target, "UIColor")
              or objectHelpers.isKindOfClass(target, "CIColor")
              or _colorIsCGColorRef(target)
          ):
              _showColor(target)
          elif objectHelpers.isKindOfClass(target, "NSData"):
              if _dataIsImage(target):
                  _showImage("(id)[UIImage imageWithData:" + target + "]")
              elif _dataIsString(target):
                  print(
                      fb.describeObject(
                          "[[NSString alloc] initWithData:" + target + " encoding:4]"
                      )
                  )
              else:
                  print("Data isn't an image and isn't a string.")
          elif objectHelpers.isKindOfClass(target, "CIImage"):
              _showImage("[UIImage imageWithCIImage:(id)" + target + "]")
          else:
              print(
                  "{} isn't supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, CIImage, CGColorRef or CVPixelBuffer.".format(
                      objectHelpers.className(target)
                  )
              )
  
  
  class FBVisualizeCommand(fb.FBCommand):
      def name(self):
          return "visualize"
  
      def description(self):
          return "Open a UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, CIImage, CGColorRef or CVPixelBuffer in Preview.app on your Mac."
  
      def args(self):
          return [
              fb.FBCommandArgument(
                  arg="target", type="(id)", help="The object to visualize."
              )
          ]
  
      def run(self, arguments, options):
          _visualize(arguments[0])
  