Проверка IP-адреса в Scala - PullRequest
       0

Проверка IP-адреса в Scala

0 голосов
/ 04 марта 2020

Я хочу подтвердить IP-адрес в scala. Я реализовал метод, но вижу некоторые ошибки.

Может кто-нибудь изучить его и предложить, если у них есть лучшее решение. Я не пытаюсь реализовать функционально.

 def validIPAddress(IP: String): String = {

       var isValidIP = true
       if(IP.contains(":")) {  
            var numbers= IP.split(":")   //create an array
            if (numbers.length!=8) return "Neither"        
            for (n <- numbers) {
                if(n.length = 0 or n.length > 4) return "Neither"    
                else {
                    for (m <- n) { 
                        if(!m in "0123456789abcdefABCDEF") return "Neither"
                    }
                }
            }
            return "IPv6"
       }
       else if(IP.contains(".") {     //192.168.1.1
              nums = IP.split(".")
              if(nums.length!=4) isValidIP = false  //Array.length
              else {
                for (a <- nums) {
                  println(a)
                  try {
                    var intA = a.toInt
                    if(intA <=0 || IntA > 255) {
                      isValid = false
                    } 

                  } catch (NumberFormatException e)  {
                    case e: Exception => None
                  }
                }

                if(isValid == true) {
                  println("Valid IP")
                } else {
                  println("Invalid IP") 
                }


              }
       } return "IPv4"

       else {
         return "neither"
       }

       }

1 Ответ

1 голос
/ 05 марта 2020

Возможно, вы не намерены реализовывать функциональность, но в вашем примере вообще нет необходимости в императивном коде, и return s и var s вызывают серьезные проблемы, когда дело доходит до чтения цели кода.

Я бы переписал код примерно так:

sealed trait IP extends Product with Serializable
object IP {
  final case class V4(a: Int, b: Int, c: Int, d: Int) extends IP
  final case class V6(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int, h: Int) extends IP
}

val ipV4 = """(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})""".r
val ipV6 = """([0-9a-fA-F]+):""".r

def validIPAddress(ip: String): Either[String, IP] = {
  def parseV4(s: String) = {
    val i = Integer.parseInt(s)
    if (0 <= i && i <= 255) Right(i) else Left(s"$i is not a valid IPv4 number")
  }
  def parseV6(s: String) = Integer.parseInt(s, 16)

  ip match {
    case ipV4(a, b, c, d) =>
      for {
        a1 <- parseV4(a)
        b1 <- parseV4(b)
        c1 <- parseV4(c)
        d1 <- parseV4(d)
      } yield IP.V4(a1, b1, c1, d1)
    case ipV6(a, b, c, d, e, f, g, h) =>
      // technically speaking this isn't exhausting all possible IPv6 addresses...
      // as this regexp would ignore e.g. ::1 or ::
      Right(IP.V6(parseV6(a), parseV6(b), parseV6(c), parseV6(d), parseV6(e), parseV6(f), parseV6(g), parseV6(h)))
    case _ =>
      Left(s"$ip is neither V4 nor V6 format")
  }
}

, чтобы упростить отслеживание и отладку ошибок, хотя, как я проверял, эта реализация НЕ действительно соответствует тому, что делает IPv6, как некоторые настройки вокруг использования регулярных выражений будет необходимо. На самом деле, я бы предпочел вообще не использовать свое собственное решение, если бы у меня не было времени написать 15-20 контрольных примеров.

Так что, если нет причин для реализации Ваш собственный валидатор. Я бы поручил эту задачу какой-то библиотеке, которая уже тестировала обработку угловых случаев.

Однако, если вам необходимо выполнить следующие действия:

  • не используйте return - в Scala он делает что-то отличное от того, что вы думаете
  • не использует var с, если вы не оптимизируете - способ их использования не имеет ничего общего с оптимизацией (isValid никогда не используется, так зачем его отменять? И другие переменные никогда не изменяются)
  • не использовать строку для всего, потому что это само по себе создает проблемы (например, "neither" и "Neither" - должен ли абонент использовать .equalsIgnoreCase в вашем коде для проверки результатов?)
  • начинать с тестов, написанных на основе спецификации. Пока я переводил ваш код, он не соответствует действительным адресам IPv6. Если бы я пропустил требование, чтобы Iv6 был фиксированного размера, он был бы еще короче:
sealed trait IP extends Product with Serializable
object IP {
  final case class V4(a: Int, b: Int, c: Int, d: Int) extends IP
  final case class V6(values: List[Int]) extends IP
}

val ipV4 = """(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})""".r
val ipV6 = """([0-9a-fA-F]*)((:[0-9a-fA-F]*){2,})""".r

def validIPAddress(ip: String): Either[String, IP] = {
  def parseV4(s: String) = {
    val i = Integer.parseInt(s)
    if (0 <= i && i <= 255) Right(i) else Left(s"$i is not a valid IPv4 number")
  }
  def parseV6(s: String) = if (s.isEmpty) 0 else Integer.parseInt(s, 16)

  ip match {
    case ipV4(a, b, c, d) =>
      for {
        a1 <- parseV4(a)
        b1 <- parseV4(b)
        c1 <- parseV4(c)
        d1 <- parseV4(d)
      } yield IP.V4(a1, b1, c1, d1)
    case ipV6(head, tail, _) =>
      val segments = head +: tail.substring(1).split(':')
      Right(IP.V6(segments.map(parseV6).toList))
    case _ =>
      Left(s"$ip is neither V4 nor V6 format")
  }
}

, который обрабатывал более правильные случаи, но все еще далек от готовности. Поэтому, если вы можете - избегайте делать это самостоятельно и используйте библиотеку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...